Spring EntityManager.persist issue
I am using a Spring framework (Boot+web+jpa) for a REST service and needs to persist an Entity called Sensor
. Since I was using Hibernate, I wanted to keep usingEntityManager
. From the Spring Data Access document and some of the questions answered in Stackoverflow, I could see that I should configure LocalEntityManagerFactoryBean
or LocalContainerEntityManagerFactoryBean
.
Now I was able to read persist.xml
and persist the entity through dependency injection @PersistenceUnit(unitName="...") EntityManagerFactory
in case for LocalContainerEntityManagerFactoryBean
. However, Spring keeps throwing an error everytime when I try to persist new Sensor()
instance with LocalEntityManagerFactoryBean
as shown below.
// LocalEntityManagerFactoryBean
@Bean
public LocalEntityManagerFactoryBean entityManagerFactory() {
LocalEntityManagerFactoryBean em = new LocalEntityManagerFactoryBean();
em.setPersistenceUnitName("myunit");
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
return em;
}
Persisting (transaction.begin and end are in the caller method):
private Sensor getSensor(SimpleData sd) {
List<Sensor> sensors = entityManager.createQuery("select s from Sensor s where s.deviceId = :devid", Sensor.class)
.setParameter("devid", sd.getDeviceId())
.getResultList();
Sensor sensor = null;
if(sensors.isEmpty()) {
sensor = new Sensor();
sensor.setDeviceId(sd.getDeviceId());
sensor.setName(sd.getName());
entityManager.persist(sensor); // Throws an exception
deviceIdMapper.put(sensor.getDeviceId(), sensor.getId());
logger.trace("Cannot find the sensor in db, adding: "+sensor.getDeviceId());
} else {
sensor = sensors.get(0);
deviceIdMapper.put(sensor.getDeviceId(), sensor.getId());
logger.trace("Found a sensor from the db: "+sd.getDeviceId());
}
deviceIdMapper.putIfAbsent(sensor.getDeviceId(), sensor.getId());
logger.trace(sensor);
return sensor;
}
Exception:
javax.persistence.PersistenceException: org.hibernate.property.access.spi.PropertyAccessException: Error accessing field [protected int com.database.Sensor.id] by reflection for persistent property [com.database.Sensor#id] : com.database.Sensor@6de9600a
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:154)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:188)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:807)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:785)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:350)
at com.sun.proxy.$Proxy108.persist(Unknown Source)
at com.DataListener.getSensor(DataListener.java:69)
at com.DataListener.lambda$0(DataListener.java:87)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
at com.DataListener.processData(DataListener.java:86)
at com.DataListener.onMessage(DataListener.java:49)
at org.apache.activemq.ActiveMQMessageConsumer.dispatch(ActiveMQMessageConsumer.java:1321)
at org.apache.activemq.ActiveMQSessionExecutor.dispatch(ActiveMQSessionExecutor.java:131)
at org.apache.activemq.ActiveMQSessionExecutor.iterate(ActiveMQSessionExecutor.java:202)
at org.apache.activemq.thread.PooledTaskRunner.runTask(PooledTaskRunner.java:129)
at org.apache.activemq.thread.PooledTaskRunner$1.run(PooledTaskRunner.java:47)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: org.hibernate.property.access.spi.PropertyAccessException: Error accessing field [protected int com.database.Sensor.id] by reflection for persistent property [com.database.Sensor#id] : com.database.Sensor@6de9600a
at org.hibernate.property.access.spi.GetterFieldImpl.get(GetterFieldImpl.java:75)
at org.hibernate.tuple.entity.AbstractEntityTuplizer.getIdentifier(AbstractEntityTuplizer.java:224)
at org.hibernate.persister.entity.AbstractEntityPersister.getIdentifier(AbstractEntityPersister.java:4931)
at org.hibernate.persister.entity.AbstractEntityPersister.isTransient(AbstractEntityPersister.java:4631)
at org.hibernate.engine.internal.ForeignKeys.isTransient(ForeignKeys.java:226)
at org.hibernate.event.internal.AbstractSaveEventListener.getEntityState(AbstractSaveEventListener.java:540)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:102)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:62)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:800)
... 20 more
Caused by: java.lang.IllegalArgumentException: Can not set int field com.database.Sensor.id to com.database.Sensor
at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:58)
at java.base/jdk.internal.reflect.UnsafeIntegerFieldAccessorImpl.getInt(UnsafeIntegerFieldAccessorImpl.java:56)
at java.base/java.lang.reflect.Field.getInt(Field.java:594)
at org.hibernate.property.access.spi.GetterFieldImpl.get(GetterFieldImpl.java:62)
... 28 more
Sensor class:
@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;
}
}
There are two questions:
- Why the error?
- Spring throws an error if I do not provide
DataSource
forLocalContainerEntityManagerFactoryBean
?LocalEntityManagerFactoryBean
uses DataSource configs frompersistence.xml
WhyLocalContainerEntityManagerFactoryBean
doesn't do the same?:
Edit 1
I think I have found a solution. If I remove spring-boot-devtools from the dependency, it fixes the problem. In fact when I use spring-boot-devtools I could not read Sensor
due to some sort of ClassLoader problem. Maybe some sort of a bug?:
java.lang.ClassCastException: class com.database.Sensor cannot be cast to class com.database.Sensor (com.database.Sensor is in unnamed module of loader 'app'; com.database.Sensor is in unnamed module of loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader @6228d409)
Edit 2
Here is 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;
}
}
Edit 3
Okay, I made a small test program that reproduces the problem: https://github.com/hjparker/spring-boot-devtools-issue.
Once the server is up, you can make a GET request to localhost:8080, which will throw an error. Commenting out spring-boot-devtools in build.gradle will solve the problem. I found this is something to do with the restart classloader in spring-dev-tools (https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-devtools.html), which reloads developing code every time spring is restarted. But I think some part of the file is not reloaded automatically causing the classcastexception, e.g. An entity loaded with CL1 != An entity loaded with CL2. Can someone explain if I am doing something wrong?
java spring hibernate spring-boot jpa
|
show 2 more comments
I am using a Spring framework (Boot+web+jpa) for a REST service and needs to persist an Entity called Sensor
. Since I was using Hibernate, I wanted to keep usingEntityManager
. From the Spring Data Access document and some of the questions answered in Stackoverflow, I could see that I should configure LocalEntityManagerFactoryBean
or LocalContainerEntityManagerFactoryBean
.
Now I was able to read persist.xml
and persist the entity through dependency injection @PersistenceUnit(unitName="...") EntityManagerFactory
in case for LocalContainerEntityManagerFactoryBean
. However, Spring keeps throwing an error everytime when I try to persist new Sensor()
instance with LocalEntityManagerFactoryBean
as shown below.
// LocalEntityManagerFactoryBean
@Bean
public LocalEntityManagerFactoryBean entityManagerFactory() {
LocalEntityManagerFactoryBean em = new LocalEntityManagerFactoryBean();
em.setPersistenceUnitName("myunit");
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
return em;
}
Persisting (transaction.begin and end are in the caller method):
private Sensor getSensor(SimpleData sd) {
List<Sensor> sensors = entityManager.createQuery("select s from Sensor s where s.deviceId = :devid", Sensor.class)
.setParameter("devid", sd.getDeviceId())
.getResultList();
Sensor sensor = null;
if(sensors.isEmpty()) {
sensor = new Sensor();
sensor.setDeviceId(sd.getDeviceId());
sensor.setName(sd.getName());
entityManager.persist(sensor); // Throws an exception
deviceIdMapper.put(sensor.getDeviceId(), sensor.getId());
logger.trace("Cannot find the sensor in db, adding: "+sensor.getDeviceId());
} else {
sensor = sensors.get(0);
deviceIdMapper.put(sensor.getDeviceId(), sensor.getId());
logger.trace("Found a sensor from the db: "+sd.getDeviceId());
}
deviceIdMapper.putIfAbsent(sensor.getDeviceId(), sensor.getId());
logger.trace(sensor);
return sensor;
}
Exception:
javax.persistence.PersistenceException: org.hibernate.property.access.spi.PropertyAccessException: Error accessing field [protected int com.database.Sensor.id] by reflection for persistent property [com.database.Sensor#id] : com.database.Sensor@6de9600a
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:154)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:188)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:807)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:785)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:350)
at com.sun.proxy.$Proxy108.persist(Unknown Source)
at com.DataListener.getSensor(DataListener.java:69)
at com.DataListener.lambda$0(DataListener.java:87)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
at com.DataListener.processData(DataListener.java:86)
at com.DataListener.onMessage(DataListener.java:49)
at org.apache.activemq.ActiveMQMessageConsumer.dispatch(ActiveMQMessageConsumer.java:1321)
at org.apache.activemq.ActiveMQSessionExecutor.dispatch(ActiveMQSessionExecutor.java:131)
at org.apache.activemq.ActiveMQSessionExecutor.iterate(ActiveMQSessionExecutor.java:202)
at org.apache.activemq.thread.PooledTaskRunner.runTask(PooledTaskRunner.java:129)
at org.apache.activemq.thread.PooledTaskRunner$1.run(PooledTaskRunner.java:47)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: org.hibernate.property.access.spi.PropertyAccessException: Error accessing field [protected int com.database.Sensor.id] by reflection for persistent property [com.database.Sensor#id] : com.database.Sensor@6de9600a
at org.hibernate.property.access.spi.GetterFieldImpl.get(GetterFieldImpl.java:75)
at org.hibernate.tuple.entity.AbstractEntityTuplizer.getIdentifier(AbstractEntityTuplizer.java:224)
at org.hibernate.persister.entity.AbstractEntityPersister.getIdentifier(AbstractEntityPersister.java:4931)
at org.hibernate.persister.entity.AbstractEntityPersister.isTransient(AbstractEntityPersister.java:4631)
at org.hibernate.engine.internal.ForeignKeys.isTransient(ForeignKeys.java:226)
at org.hibernate.event.internal.AbstractSaveEventListener.getEntityState(AbstractSaveEventListener.java:540)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:102)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:62)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:800)
... 20 more
Caused by: java.lang.IllegalArgumentException: Can not set int field com.database.Sensor.id to com.database.Sensor
at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:58)
at java.base/jdk.internal.reflect.UnsafeIntegerFieldAccessorImpl.getInt(UnsafeIntegerFieldAccessorImpl.java:56)
at java.base/java.lang.reflect.Field.getInt(Field.java:594)
at org.hibernate.property.access.spi.GetterFieldImpl.get(GetterFieldImpl.java:62)
... 28 more
Sensor class:
@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;
}
}
There are two questions:
- Why the error?
- Spring throws an error if I do not provide
DataSource
forLocalContainerEntityManagerFactoryBean
?LocalEntityManagerFactoryBean
uses DataSource configs frompersistence.xml
WhyLocalContainerEntityManagerFactoryBean
doesn't do the same?:
Edit 1
I think I have found a solution. If I remove spring-boot-devtools from the dependency, it fixes the problem. In fact when I use spring-boot-devtools I could not read Sensor
due to some sort of ClassLoader problem. Maybe some sort of a bug?:
java.lang.ClassCastException: class com.database.Sensor cannot be cast to class com.database.Sensor (com.database.Sensor is in unnamed module of loader 'app'; com.database.Sensor is in unnamed module of loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader @6228d409)
Edit 2
Here is 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;
}
}
Edit 3
Okay, I made a small test program that reproduces the problem: https://github.com/hjparker/spring-boot-devtools-issue.
Once the server is up, you can make a GET request to localhost:8080, which will throw an error. Commenting out spring-boot-devtools in build.gradle will solve the problem. I found this is something to do with the restart classloader in spring-dev-tools (https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-devtools.html), which reloads developing code every time spring is restarted. But I think some part of the file is not reloaded automatically causing the classcastexception, e.g. An entity loaded with CL1 != An entity loaded with CL2. Can someone explain if I am doing something wrong?
java spring hibernate spring-boot jpa
Are you using Spring Boot at all? Note that your error message specifically refers to yourSensor
class, which you failed to include.
– chrylis
Nov 25 '18 at 1:21
Sorry, I edited the question to include the Sensor class. Yes I am using Spring Boot.
– Domination
Nov 25 '18 at 1:25
1
If you're using Boot, then stop configuring all of the JPA system by hand and just let Boot do it for you. That said, I don't think your Hibernate setup is the problem here; it looks to be something with your class. Try usingInteger
for your ID field (and note that most of the time, if you're using integral types,Long
is the way to go because 32 bits isn't that much, especially if you have sequences).
– chrylis
Nov 25 '18 at 1:36
It's better to use wrapper than primitve type so try to use protected Integer id;
– TinyOS
Nov 25 '18 at 1:41
I think I have found a solution. I needed to remove spring-devtools from the dependencies. But wondering why? If i have devtools and try to read the Sensor class from the DB, the following error occurs. java.lang.ClassCastException: class com.database.Sensor cannot be cast to class com.database.Sensor (com.database.Sensor is in unnamed module of loader 'app'; com.database.Sensor is in unnamed module of loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader @6228d409)
– Domination
Nov 25 '18 at 2:07
|
show 2 more comments
I am using a Spring framework (Boot+web+jpa) for a REST service and needs to persist an Entity called Sensor
. Since I was using Hibernate, I wanted to keep usingEntityManager
. From the Spring Data Access document and some of the questions answered in Stackoverflow, I could see that I should configure LocalEntityManagerFactoryBean
or LocalContainerEntityManagerFactoryBean
.
Now I was able to read persist.xml
and persist the entity through dependency injection @PersistenceUnit(unitName="...") EntityManagerFactory
in case for LocalContainerEntityManagerFactoryBean
. However, Spring keeps throwing an error everytime when I try to persist new Sensor()
instance with LocalEntityManagerFactoryBean
as shown below.
// LocalEntityManagerFactoryBean
@Bean
public LocalEntityManagerFactoryBean entityManagerFactory() {
LocalEntityManagerFactoryBean em = new LocalEntityManagerFactoryBean();
em.setPersistenceUnitName("myunit");
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
return em;
}
Persisting (transaction.begin and end are in the caller method):
private Sensor getSensor(SimpleData sd) {
List<Sensor> sensors = entityManager.createQuery("select s from Sensor s where s.deviceId = :devid", Sensor.class)
.setParameter("devid", sd.getDeviceId())
.getResultList();
Sensor sensor = null;
if(sensors.isEmpty()) {
sensor = new Sensor();
sensor.setDeviceId(sd.getDeviceId());
sensor.setName(sd.getName());
entityManager.persist(sensor); // Throws an exception
deviceIdMapper.put(sensor.getDeviceId(), sensor.getId());
logger.trace("Cannot find the sensor in db, adding: "+sensor.getDeviceId());
} else {
sensor = sensors.get(0);
deviceIdMapper.put(sensor.getDeviceId(), sensor.getId());
logger.trace("Found a sensor from the db: "+sd.getDeviceId());
}
deviceIdMapper.putIfAbsent(sensor.getDeviceId(), sensor.getId());
logger.trace(sensor);
return sensor;
}
Exception:
javax.persistence.PersistenceException: org.hibernate.property.access.spi.PropertyAccessException: Error accessing field [protected int com.database.Sensor.id] by reflection for persistent property [com.database.Sensor#id] : com.database.Sensor@6de9600a
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:154)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:188)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:807)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:785)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:350)
at com.sun.proxy.$Proxy108.persist(Unknown Source)
at com.DataListener.getSensor(DataListener.java:69)
at com.DataListener.lambda$0(DataListener.java:87)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
at com.DataListener.processData(DataListener.java:86)
at com.DataListener.onMessage(DataListener.java:49)
at org.apache.activemq.ActiveMQMessageConsumer.dispatch(ActiveMQMessageConsumer.java:1321)
at org.apache.activemq.ActiveMQSessionExecutor.dispatch(ActiveMQSessionExecutor.java:131)
at org.apache.activemq.ActiveMQSessionExecutor.iterate(ActiveMQSessionExecutor.java:202)
at org.apache.activemq.thread.PooledTaskRunner.runTask(PooledTaskRunner.java:129)
at org.apache.activemq.thread.PooledTaskRunner$1.run(PooledTaskRunner.java:47)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: org.hibernate.property.access.spi.PropertyAccessException: Error accessing field [protected int com.database.Sensor.id] by reflection for persistent property [com.database.Sensor#id] : com.database.Sensor@6de9600a
at org.hibernate.property.access.spi.GetterFieldImpl.get(GetterFieldImpl.java:75)
at org.hibernate.tuple.entity.AbstractEntityTuplizer.getIdentifier(AbstractEntityTuplizer.java:224)
at org.hibernate.persister.entity.AbstractEntityPersister.getIdentifier(AbstractEntityPersister.java:4931)
at org.hibernate.persister.entity.AbstractEntityPersister.isTransient(AbstractEntityPersister.java:4631)
at org.hibernate.engine.internal.ForeignKeys.isTransient(ForeignKeys.java:226)
at org.hibernate.event.internal.AbstractSaveEventListener.getEntityState(AbstractSaveEventListener.java:540)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:102)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:62)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:800)
... 20 more
Caused by: java.lang.IllegalArgumentException: Can not set int field com.database.Sensor.id to com.database.Sensor
at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:58)
at java.base/jdk.internal.reflect.UnsafeIntegerFieldAccessorImpl.getInt(UnsafeIntegerFieldAccessorImpl.java:56)
at java.base/java.lang.reflect.Field.getInt(Field.java:594)
at org.hibernate.property.access.spi.GetterFieldImpl.get(GetterFieldImpl.java:62)
... 28 more
Sensor class:
@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;
}
}
There are two questions:
- Why the error?
- Spring throws an error if I do not provide
DataSource
forLocalContainerEntityManagerFactoryBean
?LocalEntityManagerFactoryBean
uses DataSource configs frompersistence.xml
WhyLocalContainerEntityManagerFactoryBean
doesn't do the same?:
Edit 1
I think I have found a solution. If I remove spring-boot-devtools from the dependency, it fixes the problem. In fact when I use spring-boot-devtools I could not read Sensor
due to some sort of ClassLoader problem. Maybe some sort of a bug?:
java.lang.ClassCastException: class com.database.Sensor cannot be cast to class com.database.Sensor (com.database.Sensor is in unnamed module of loader 'app'; com.database.Sensor is in unnamed module of loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader @6228d409)
Edit 2
Here is 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;
}
}
Edit 3
Okay, I made a small test program that reproduces the problem: https://github.com/hjparker/spring-boot-devtools-issue.
Once the server is up, you can make a GET request to localhost:8080, which will throw an error. Commenting out spring-boot-devtools in build.gradle will solve the problem. I found this is something to do with the restart classloader in spring-dev-tools (https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-devtools.html), which reloads developing code every time spring is restarted. But I think some part of the file is not reloaded automatically causing the classcastexception, e.g. An entity loaded with CL1 != An entity loaded with CL2. Can someone explain if I am doing something wrong?
java spring hibernate spring-boot jpa
I am using a Spring framework (Boot+web+jpa) for a REST service and needs to persist an Entity called Sensor
. Since I was using Hibernate, I wanted to keep usingEntityManager
. From the Spring Data Access document and some of the questions answered in Stackoverflow, I could see that I should configure LocalEntityManagerFactoryBean
or LocalContainerEntityManagerFactoryBean
.
Now I was able to read persist.xml
and persist the entity through dependency injection @PersistenceUnit(unitName="...") EntityManagerFactory
in case for LocalContainerEntityManagerFactoryBean
. However, Spring keeps throwing an error everytime when I try to persist new Sensor()
instance with LocalEntityManagerFactoryBean
as shown below.
// LocalEntityManagerFactoryBean
@Bean
public LocalEntityManagerFactoryBean entityManagerFactory() {
LocalEntityManagerFactoryBean em = new LocalEntityManagerFactoryBean();
em.setPersistenceUnitName("myunit");
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
return em;
}
Persisting (transaction.begin and end are in the caller method):
private Sensor getSensor(SimpleData sd) {
List<Sensor> sensors = entityManager.createQuery("select s from Sensor s where s.deviceId = :devid", Sensor.class)
.setParameter("devid", sd.getDeviceId())
.getResultList();
Sensor sensor = null;
if(sensors.isEmpty()) {
sensor = new Sensor();
sensor.setDeviceId(sd.getDeviceId());
sensor.setName(sd.getName());
entityManager.persist(sensor); // Throws an exception
deviceIdMapper.put(sensor.getDeviceId(), sensor.getId());
logger.trace("Cannot find the sensor in db, adding: "+sensor.getDeviceId());
} else {
sensor = sensors.get(0);
deviceIdMapper.put(sensor.getDeviceId(), sensor.getId());
logger.trace("Found a sensor from the db: "+sd.getDeviceId());
}
deviceIdMapper.putIfAbsent(sensor.getDeviceId(), sensor.getId());
logger.trace(sensor);
return sensor;
}
Exception:
javax.persistence.PersistenceException: org.hibernate.property.access.spi.PropertyAccessException: Error accessing field [protected int com.database.Sensor.id] by reflection for persistent property [com.database.Sensor#id] : com.database.Sensor@6de9600a
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:154)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:188)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:807)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:785)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:350)
at com.sun.proxy.$Proxy108.persist(Unknown Source)
at com.DataListener.getSensor(DataListener.java:69)
at com.DataListener.lambda$0(DataListener.java:87)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
at com.DataListener.processData(DataListener.java:86)
at com.DataListener.onMessage(DataListener.java:49)
at org.apache.activemq.ActiveMQMessageConsumer.dispatch(ActiveMQMessageConsumer.java:1321)
at org.apache.activemq.ActiveMQSessionExecutor.dispatch(ActiveMQSessionExecutor.java:131)
at org.apache.activemq.ActiveMQSessionExecutor.iterate(ActiveMQSessionExecutor.java:202)
at org.apache.activemq.thread.PooledTaskRunner.runTask(PooledTaskRunner.java:129)
at org.apache.activemq.thread.PooledTaskRunner$1.run(PooledTaskRunner.java:47)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: org.hibernate.property.access.spi.PropertyAccessException: Error accessing field [protected int com.database.Sensor.id] by reflection for persistent property [com.database.Sensor#id] : com.database.Sensor@6de9600a
at org.hibernate.property.access.spi.GetterFieldImpl.get(GetterFieldImpl.java:75)
at org.hibernate.tuple.entity.AbstractEntityTuplizer.getIdentifier(AbstractEntityTuplizer.java:224)
at org.hibernate.persister.entity.AbstractEntityPersister.getIdentifier(AbstractEntityPersister.java:4931)
at org.hibernate.persister.entity.AbstractEntityPersister.isTransient(AbstractEntityPersister.java:4631)
at org.hibernate.engine.internal.ForeignKeys.isTransient(ForeignKeys.java:226)
at org.hibernate.event.internal.AbstractSaveEventListener.getEntityState(AbstractSaveEventListener.java:540)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:102)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:62)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:800)
... 20 more
Caused by: java.lang.IllegalArgumentException: Can not set int field com.database.Sensor.id to com.database.Sensor
at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:58)
at java.base/jdk.internal.reflect.UnsafeIntegerFieldAccessorImpl.getInt(UnsafeIntegerFieldAccessorImpl.java:56)
at java.base/java.lang.reflect.Field.getInt(Field.java:594)
at org.hibernate.property.access.spi.GetterFieldImpl.get(GetterFieldImpl.java:62)
... 28 more
Sensor class:
@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;
}
}
There are two questions:
- Why the error?
- Spring throws an error if I do not provide
DataSource
forLocalContainerEntityManagerFactoryBean
?LocalEntityManagerFactoryBean
uses DataSource configs frompersistence.xml
WhyLocalContainerEntityManagerFactoryBean
doesn't do the same?:
Edit 1
I think I have found a solution. If I remove spring-boot-devtools from the dependency, it fixes the problem. In fact when I use spring-boot-devtools I could not read Sensor
due to some sort of ClassLoader problem. Maybe some sort of a bug?:
java.lang.ClassCastException: class com.database.Sensor cannot be cast to class com.database.Sensor (com.database.Sensor is in unnamed module of loader 'app'; com.database.Sensor is in unnamed module of loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader @6228d409)
Edit 2
Here is 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;
}
}
Edit 3
Okay, I made a small test program that reproduces the problem: https://github.com/hjparker/spring-boot-devtools-issue.
Once the server is up, you can make a GET request to localhost:8080, which will throw an error. Commenting out spring-boot-devtools in build.gradle will solve the problem. I found this is something to do with the restart classloader in spring-dev-tools (https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-devtools.html), which reloads developing code every time spring is restarted. But I think some part of the file is not reloaded automatically causing the classcastexception, e.g. An entity loaded with CL1 != An entity loaded with CL2. Can someone explain if I am doing something wrong?
java spring hibernate spring-boot jpa
java spring hibernate spring-boot jpa
edited Nov 25 '18 at 14:11
Domination
asked Nov 25 '18 at 1:16
DominationDomination
415
415
Are you using Spring Boot at all? Note that your error message specifically refers to yourSensor
class, which you failed to include.
– chrylis
Nov 25 '18 at 1:21
Sorry, I edited the question to include the Sensor class. Yes I am using Spring Boot.
– Domination
Nov 25 '18 at 1:25
1
If you're using Boot, then stop configuring all of the JPA system by hand and just let Boot do it for you. That said, I don't think your Hibernate setup is the problem here; it looks to be something with your class. Try usingInteger
for your ID field (and note that most of the time, if you're using integral types,Long
is the way to go because 32 bits isn't that much, especially if you have sequences).
– chrylis
Nov 25 '18 at 1:36
It's better to use wrapper than primitve type so try to use protected Integer id;
– TinyOS
Nov 25 '18 at 1:41
I think I have found a solution. I needed to remove spring-devtools from the dependencies. But wondering why? If i have devtools and try to read the Sensor class from the DB, the following error occurs. java.lang.ClassCastException: class com.database.Sensor cannot be cast to class com.database.Sensor (com.database.Sensor is in unnamed module of loader 'app'; com.database.Sensor is in unnamed module of loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader @6228d409)
– Domination
Nov 25 '18 at 2:07
|
show 2 more comments
Are you using Spring Boot at all? Note that your error message specifically refers to yourSensor
class, which you failed to include.
– chrylis
Nov 25 '18 at 1:21
Sorry, I edited the question to include the Sensor class. Yes I am using Spring Boot.
– Domination
Nov 25 '18 at 1:25
1
If you're using Boot, then stop configuring all of the JPA system by hand and just let Boot do it for you. That said, I don't think your Hibernate setup is the problem here; it looks to be something with your class. Try usingInteger
for your ID field (and note that most of the time, if you're using integral types,Long
is the way to go because 32 bits isn't that much, especially if you have sequences).
– chrylis
Nov 25 '18 at 1:36
It's better to use wrapper than primitve type so try to use protected Integer id;
– TinyOS
Nov 25 '18 at 1:41
I think I have found a solution. I needed to remove spring-devtools from the dependencies. But wondering why? If i have devtools and try to read the Sensor class from the DB, the following error occurs. java.lang.ClassCastException: class com.database.Sensor cannot be cast to class com.database.Sensor (com.database.Sensor is in unnamed module of loader 'app'; com.database.Sensor is in unnamed module of loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader @6228d409)
– Domination
Nov 25 '18 at 2:07
Are you using Spring Boot at all? Note that your error message specifically refers to your
Sensor
class, which you failed to include.– chrylis
Nov 25 '18 at 1:21
Are you using Spring Boot at all? Note that your error message specifically refers to your
Sensor
class, which you failed to include.– chrylis
Nov 25 '18 at 1:21
Sorry, I edited the question to include the Sensor class. Yes I am using Spring Boot.
– Domination
Nov 25 '18 at 1:25
Sorry, I edited the question to include the Sensor class. Yes I am using Spring Boot.
– Domination
Nov 25 '18 at 1:25
1
1
If you're using Boot, then stop configuring all of the JPA system by hand and just let Boot do it for you. That said, I don't think your Hibernate setup is the problem here; it looks to be something with your class. Try using
Integer
for your ID field (and note that most of the time, if you're using integral types, Long
is the way to go because 32 bits isn't that much, especially if you have sequences).– chrylis
Nov 25 '18 at 1:36
If you're using Boot, then stop configuring all of the JPA system by hand and just let Boot do it for you. That said, I don't think your Hibernate setup is the problem here; it looks to be something with your class. Try using
Integer
for your ID field (and note that most of the time, if you're using integral types, Long
is the way to go because 32 bits isn't that much, especially if you have sequences).– chrylis
Nov 25 '18 at 1:36
It's better to use wrapper than primitve type so try to use protected Integer id;
– TinyOS
Nov 25 '18 at 1:41
It's better to use wrapper than primitve type so try to use protected Integer id;
– TinyOS
Nov 25 '18 at 1:41
I think I have found a solution. I needed to remove spring-devtools from the dependencies. But wondering why? If i have devtools and try to read the Sensor class from the DB, the following error occurs. java.lang.ClassCastException: class com.database.Sensor cannot be cast to class com.database.Sensor (com.database.Sensor is in unnamed module of loader 'app'; com.database.Sensor is in unnamed module of loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader @6228d409)
– Domination
Nov 25 '18 at 2:07
I think I have found a solution. I needed to remove spring-devtools from the dependencies. But wondering why? If i have devtools and try to read the Sensor class from the DB, the following error occurs. java.lang.ClassCastException: class com.database.Sensor cannot be cast to class com.database.Sensor (com.database.Sensor is in unnamed module of loader 'app'; com.database.Sensor is in unnamed module of loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader @6228d409)
– Domination
Nov 25 '18 at 2:07
|
show 2 more comments
2 Answers
2
active
oldest
votes
Need to update access modifier private instead of protected, seems that Java persistence tries to get id which is not in package neither is called on some subclass.
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String deviceId;
private String name;
Access modifier documentation
Changed it to private but the result is the same. As I mentioned in the edit, the problem was due to the spring-boot-devtools. I am now wondering what makes this causing the problem. I think it is something to do with two Sensor instances from different ClassLoader due to the addition of spring-boot-devtools.
– Domination
Nov 25 '18 at 4:54
It's OK so what can I help you? could you please share your repo?
– Jonathan Johx
Nov 25 '18 at 5:14
I made a small program that produces the problem, please see the updated question.
– Domination
Nov 25 '18 at 14:10
add a comment |
It seems some of the deserializers for Entity or Bean classes managed by hibernate/Spring ORM are not reloaded by the spring-boot-devtools restart classloader properly. I had to explicitly include the classes that perform deserialization to the restart classloader by setting the following properties in META-INF/spring-devtools.properties
:
restart.include.hibernate=hibernate.*
restart.include.spring-orm=spring-orm.*
Sources:
https://github.com/AxonFramework/AxonFramework/issues/344
https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-devtools.html#using-boot-devtools-customizing-classload
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53463874%2fspring-entitymanager-persist-issue%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
Need to update access modifier private instead of protected, seems that Java persistence tries to get id which is not in package neither is called on some subclass.
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String deviceId;
private String name;
Access modifier documentation
Changed it to private but the result is the same. As I mentioned in the edit, the problem was due to the spring-boot-devtools. I am now wondering what makes this causing the problem. I think it is something to do with two Sensor instances from different ClassLoader due to the addition of spring-boot-devtools.
– Domination
Nov 25 '18 at 4:54
It's OK so what can I help you? could you please share your repo?
– Jonathan Johx
Nov 25 '18 at 5:14
I made a small program that produces the problem, please see the updated question.
– Domination
Nov 25 '18 at 14:10
add a comment |
Need to update access modifier private instead of protected, seems that Java persistence tries to get id which is not in package neither is called on some subclass.
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String deviceId;
private String name;
Access modifier documentation
Changed it to private but the result is the same. As I mentioned in the edit, the problem was due to the spring-boot-devtools. I am now wondering what makes this causing the problem. I think it is something to do with two Sensor instances from different ClassLoader due to the addition of spring-boot-devtools.
– Domination
Nov 25 '18 at 4:54
It's OK so what can I help you? could you please share your repo?
– Jonathan Johx
Nov 25 '18 at 5:14
I made a small program that produces the problem, please see the updated question.
– Domination
Nov 25 '18 at 14:10
add a comment |
Need to update access modifier private instead of protected, seems that Java persistence tries to get id which is not in package neither is called on some subclass.
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String deviceId;
private String name;
Access modifier documentation
Need to update access modifier private instead of protected, seems that Java persistence tries to get id which is not in package neither is called on some subclass.
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String deviceId;
private String name;
Access modifier documentation
answered Nov 25 '18 at 4:25
Jonathan JohxJonathan Johx
1,7751317
1,7751317
Changed it to private but the result is the same. As I mentioned in the edit, the problem was due to the spring-boot-devtools. I am now wondering what makes this causing the problem. I think it is something to do with two Sensor instances from different ClassLoader due to the addition of spring-boot-devtools.
– Domination
Nov 25 '18 at 4:54
It's OK so what can I help you? could you please share your repo?
– Jonathan Johx
Nov 25 '18 at 5:14
I made a small program that produces the problem, please see the updated question.
– Domination
Nov 25 '18 at 14:10
add a comment |
Changed it to private but the result is the same. As I mentioned in the edit, the problem was due to the spring-boot-devtools. I am now wondering what makes this causing the problem. I think it is something to do with two Sensor instances from different ClassLoader due to the addition of spring-boot-devtools.
– Domination
Nov 25 '18 at 4:54
It's OK so what can I help you? could you please share your repo?
– Jonathan Johx
Nov 25 '18 at 5:14
I made a small program that produces the problem, please see the updated question.
– Domination
Nov 25 '18 at 14:10
Changed it to private but the result is the same. As I mentioned in the edit, the problem was due to the spring-boot-devtools. I am now wondering what makes this causing the problem. I think it is something to do with two Sensor instances from different ClassLoader due to the addition of spring-boot-devtools.
– Domination
Nov 25 '18 at 4:54
Changed it to private but the result is the same. As I mentioned in the edit, the problem was due to the spring-boot-devtools. I am now wondering what makes this causing the problem. I think it is something to do with two Sensor instances from different ClassLoader due to the addition of spring-boot-devtools.
– Domination
Nov 25 '18 at 4:54
It's OK so what can I help you? could you please share your repo?
– Jonathan Johx
Nov 25 '18 at 5:14
It's OK so what can I help you? could you please share your repo?
– Jonathan Johx
Nov 25 '18 at 5:14
I made a small program that produces the problem, please see the updated question.
– Domination
Nov 25 '18 at 14:10
I made a small program that produces the problem, please see the updated question.
– Domination
Nov 25 '18 at 14:10
add a comment |
It seems some of the deserializers for Entity or Bean classes managed by hibernate/Spring ORM are not reloaded by the spring-boot-devtools restart classloader properly. I had to explicitly include the classes that perform deserialization to the restart classloader by setting the following properties in META-INF/spring-devtools.properties
:
restart.include.hibernate=hibernate.*
restart.include.spring-orm=spring-orm.*
Sources:
https://github.com/AxonFramework/AxonFramework/issues/344
https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-devtools.html#using-boot-devtools-customizing-classload
add a comment |
It seems some of the deserializers for Entity or Bean classes managed by hibernate/Spring ORM are not reloaded by the spring-boot-devtools restart classloader properly. I had to explicitly include the classes that perform deserialization to the restart classloader by setting the following properties in META-INF/spring-devtools.properties
:
restart.include.hibernate=hibernate.*
restart.include.spring-orm=spring-orm.*
Sources:
https://github.com/AxonFramework/AxonFramework/issues/344
https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-devtools.html#using-boot-devtools-customizing-classload
add a comment |
It seems some of the deserializers for Entity or Bean classes managed by hibernate/Spring ORM are not reloaded by the spring-boot-devtools restart classloader properly. I had to explicitly include the classes that perform deserialization to the restart classloader by setting the following properties in META-INF/spring-devtools.properties
:
restart.include.hibernate=hibernate.*
restart.include.spring-orm=spring-orm.*
Sources:
https://github.com/AxonFramework/AxonFramework/issues/344
https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-devtools.html#using-boot-devtools-customizing-classload
It seems some of the deserializers for Entity or Bean classes managed by hibernate/Spring ORM are not reloaded by the spring-boot-devtools restart classloader properly. I had to explicitly include the classes that perform deserialization to the restart classloader by setting the following properties in META-INF/spring-devtools.properties
:
restart.include.hibernate=hibernate.*
restart.include.spring-orm=spring-orm.*
Sources:
https://github.com/AxonFramework/AxonFramework/issues/344
https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-devtools.html#using-boot-devtools-customizing-classload
answered Dec 2 '18 at 2:30
DominationDomination
415
415
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53463874%2fspring-entitymanager-persist-issue%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Are you using Spring Boot at all? Note that your error message specifically refers to your
Sensor
class, which you failed to include.– chrylis
Nov 25 '18 at 1:21
Sorry, I edited the question to include the Sensor class. Yes I am using Spring Boot.
– Domination
Nov 25 '18 at 1:25
1
If you're using Boot, then stop configuring all of the JPA system by hand and just let Boot do it for you. That said, I don't think your Hibernate setup is the problem here; it looks to be something with your class. Try using
Integer
for your ID field (and note that most of the time, if you're using integral types,Long
is the way to go because 32 bits isn't that much, especially if you have sequences).– chrylis
Nov 25 '18 at 1:36
It's better to use wrapper than primitve type so try to use protected Integer id;
– TinyOS
Nov 25 '18 at 1:41
I think I have found a solution. I needed to remove spring-devtools from the dependencies. But wondering why? If i have devtools and try to read the Sensor class from the DB, the following error occurs. java.lang.ClassCastException: class com.database.Sensor cannot be cast to class com.database.Sensor (com.database.Sensor is in unnamed module of loader 'app'; com.database.Sensor is in unnamed module of loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader @6228d409)
– Domination
Nov 25 '18 at 2:07