Java Spring EntityManager.persist问题

Java Spring EntityManager.persist问题,java,spring,hibernate,spring-boot,jpa,Java,Spring,Hibernate,Spring Boot,Jpa,我正在为REST服务使用Spring框架(Boot+web+jpa),需要持久化一个名为Sensor的实体。因为我使用的是Hibernate,所以我想继续使用EntityManager。从Spring数据访问文档和Stackoverflow中回答的一些问题中,我可以看到我应该配置LocalEntityManagerFactoryBean或LocalContainerEntityManagerFactoryBean 现在我能够读取persist.xml,并通过依赖项注入@PersistenceUn

我正在为REST服务使用Spring框架(Boot+web+jpa),需要持久化一个名为
Sensor
的实体。因为我使用的是Hibernate,所以我想继续使用
EntityManager
。从Spring数据访问文档和Stackoverflow中回答的一些问题中,我可以看到我应该配置
LocalEntityManagerFactoryBean
LocalContainerEntityManagerFactoryBean

现在我能够读取
persist.xml
,并通过依赖项注入
@PersistenceUnit(unitName=“…”).EntityManagerFactory来持久化实体,以防
LocalContainerEntityManagerFactoryBean
。但是,每当我尝试使用
LocalEntityManagerFactoryBean
持久化
newsensor()
实例时,Spring总是抛出一个错误,如下所示

// LocalEntityManagerFactoryBean
@Bean
public LocalEntityManagerFactoryBean entityManagerFactory() {
    LocalEntityManagerFactoryBean em = new LocalEntityManagerFactoryBean();
    em.setPersistenceUnitName("myunit");
    JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    em.setJpaVendorAdapter(vendorAdapter);
    return em;
}
持久化(transaction.begin和end在调用方方法中):

传感器等级:

@Entity
public class Sensor {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    protected int id;
    protected String deviceId;
    protected String name;

    @OneToMany(mappedBy = "owner", cascade=CascadeType.ALL)
    private List<SimpleData> simpleDevices = new ArrayList<>();

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDeviceId() {
        return deviceId;
    }

    public void setDeviceId(String deviceId) {
        this.deviceId = deviceId;
    }


    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public List<SimpleData> getSimpleDevices() {
        return simpleDevices;
    }

    public void setSimpleDevices(List<SimpleData> simpleDevices) {
        this.simpleDevices = simpleDevices;
    }

}
编辑2 下面是
SimpleData
class

@Entity
public class SimpleData {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    private double value;

    @JsonIgnore
    private Date time;

    @Transient
    private String deviceId;

    @JsonIgnore
    @Transient
    private String name;

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="sensor_id")
    private Sensor owner;

    public double getValue() {
        return value;
    }

    public void setValue(double value) {
        this.value = value;
    }

    public Date getTime() {
        return time;
    }

    public void setTime(Date time) {
        this.time = time;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDeviceId() {
        return deviceId;
    }

    public void setDeviceId(String deviceId) {
        this.deviceId = deviceId;
    }

    public Sensor getOwner() {
        return owner;
    }

    public void setOwner(Sensor owner) {
        this.owner = owner;
    }
}
编辑3

好的,我做了一个小的测试程序来重现这个问题:


服务器启动后,您可以向localhost:8080发出GET请求,这将抛出一个错误。在build.gradle中注释掉spring boot devtools将解决这个问题。我发现这与springdevtools()中的restartclassloader有关,每次spring重新启动时,它都会重新加载开发代码。但我认为文件的某些部分不会自动重新加载,从而导致classcastexception,例如,加载了CL1!=加载了CL2的实体。有人能解释一下我是否做错了吗?

需要更新访问修饰符private而不是protected,似乎Java persistence试图获取不在包中的id,也不在某些子类上调用

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String deviceId;
private String name;

似乎hibernate/Spring ORM管理的实体或Bean类的一些反序列化程序没有被Spring boot devtools重新启动类加载器正确地重新加载。通过在
META-INF/spring devtools.properties中设置以下属性,我必须显式地将执行反序列化的类包含到重启类加载器中:

restart.include.hibernate=hibernate.*
restart.include.spring-orm=spring-orm.*
资料来源:


您使用的是弹簧靴吗?请注意,您的错误消息特别指的是您的
传感器
类,您未能将其包括在内。很抱歉,我编辑了该问题以将传感器类包括在内。是的,我使用的是SpringBoot。如果您使用的是Boot,那么停止手动配置所有JPA系统,让Boot为您完成。也就是说,我不认为您的Hibernate设置是这里的问题;这看起来和你们班有些关系。尝试对ID字段使用
Integer
(请注意,大多数情况下,如果使用整数类型,
Long
是最好的选择,因为32位并不多,尤其是在有序列的情况下)。使用wrapper比primitve type更好,因此请尝试使用受保护的整数ID;我想我已经找到了解决办法。我需要从依赖项中删除spring开发工具。但是想知道为什么?如果我有devtools并尝试从DB读取Sensor类,则会发生以下错误。java.lang.ClassCastException:class com.database.Sensor无法强制转换为class com.database.Sensor(com.database.Sensor位于加载程序“app”的未命名模块中;com.database.Sensor位于加载程序org.springframework.boot.devtools.restart.classloader.RestartClassLoader@6228d409的未命名模块中)将其更改为private,但结果相同。正如我在编辑中提到的,问题是由spring boot开发工具造成的。我现在想知道是什么原因导致了这个问题。由于添加了spring boot开发工具,我认为这与来自不同类加载器的两个传感器实例有关。没关系,我能为您做些什么?你能分享你的回购协议吗?我做了一个小程序,产生了这个问题,请看更新的问题。
@Entity
public class SimpleData {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    private double value;

    @JsonIgnore
    private Date time;

    @Transient
    private String deviceId;

    @JsonIgnore
    @Transient
    private String name;

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="sensor_id")
    private Sensor owner;

    public double getValue() {
        return value;
    }

    public void setValue(double value) {
        this.value = value;
    }

    public Date getTime() {
        return time;
    }

    public void setTime(Date time) {
        this.time = time;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDeviceId() {
        return deviceId;
    }

    public void setDeviceId(String deviceId) {
        this.deviceId = deviceId;
    }

    public Sensor getOwner() {
        return owner;
    }

    public void setOwner(Sensor owner) {
        this.owner = owner;
    }
}
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String deviceId;
private String name;
restart.include.hibernate=hibernate.*
restart.include.spring-orm=spring-orm.*