Java Spring EntityManager.persist问题
我正在为REST服务使用Spring框架(Boot+web+jpa),需要持久化一个名为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
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.*