My database
{code:sql} CREATE TABLE public.users ( uuid uuid NOT NULL, id int4 NOT NULL, "name" varchar(255) NULL, salary int4 NULL, CONSTRAINT uk_6jvqtxgs6xvh0h0t261hurgqo UNIQUE (uuid), CONSTRAINT users_pkey PRIMARY KEY (id) );
CREATE TABLE public.teams ( user_id int4 NOT NULL, "name" varchar(255) NULL, CONSTRAINT teams_users_fk FOREIGN KEY (user_id) REFERENCES public.users(id) );
INSERT INTO public.users (uuid,id,"name",salary) VALUES ('cbfaed14-bb65-11e7-abc4-cec278b6b50a',1,'name',12);
INSERT INTO public.users (uuid,id,"name",salary) VALUES ('44af28c2-bbdb-11e7-abc4-cec278b6b50a',2,'name 2',20);
INSERT INTO public.teams (user_id,"name") VALUES (2,'team 1'); {code}
I have one Entity and an embeddable collection
{code:java} @Entity @Table(name = "users", catalog = "test") public class Users implements Serializable {
@Id private UUID uuid;
@Column(name = "id") private Integer id;
@Column(name = "name") private String name;
private Integer salary;
@ElementCollection(fetch = FetchType.EAGER) @CollectionTable(name = "teams", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id")) private Collection<Team> teams;
public Collection<Team> getTeams() { return teams; }
public void setTeams(Collection<Team> teams) { this.teams = teams; }
public Users() { }
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public Integer getSalary() { return salary; }
public void setSalary(Integer salary) { this.salary = salary; }
public UUID getUuid() { return uuid; }
public void setUuid(UUID uuid) { this.uuid = uuid; } } {code}
And
{code:java} @Embeddable public class Team { public String getName() { return name; }
public void setName(String name) { this.name = name; }
private String name; } {code}
The problem arrives when I set the fetch type to EAGER on the collection teams
the code: [Collection _teams_ is empty]
{code:java} entityManager.find(Users.class, UUID.fromString("cbfaed14-bb65-11e7-abc4-cec278b6b50a")); {code}
generate an error:
{noformat} org.hibernate.property.access.spi.PropertyAccessException: Error accessing field [private java.lang.Integer com.techprimers.jpa.springjpahibernateexample.model.Users.id] by reflection for persistent property [com.techprimers.jpa.springjpahibernateexample.model.Users#id] : cbfaed14-bb65-11e7-abc4-cec278b6b50a at org.hibernate.property.access.spi.GetterFieldImpl.get(GetterFieldImpl.java:43) at org.hibernate.tuple.component.AbstractComponentTuplizer.getPropertyValue(AbstractComponentTuplizer.java:58) at org.hibernate.type.ComponentType.getPropertyValue(ComponentType.java:419) at org.hibernate.type.ComponentType.getHashCode(ComponentType.java:242) at org.hibernate.engine.spi.CollectionKey.generateHashCode(CollectionKey.java:64) at org.hibernate.engine.spi.CollectionKey.<init>(CollectionKey.java:58) at org.hibernate.engine.spi.CollectionKey.<init>(CollectionKey.java:43) at org.hibernate.engine.loading.internal.CollectionLoadContext.getLoadingCollection(CollectionLoadContext.java:95) at org.hibernate.loader.plan.exec.process.internal.CollectionReferenceInitializerImpl.finishUpRow(CollectionReferenceInitializerImpl.java:105) at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.readRow(AbstractRowReader.java:121) at org.hibernate.loader.plan.exec.internal.EntityLoadQueryDetails$EntityLoaderRowReader.readRow(EntityLoadQueryDetails.java:239) at org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(ResultSetProcessorImpl.java:122) at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:122) at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:86) at org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.load(AbstractLoadPlanBasedEntityLoader.java:167) at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:4019) at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:508) at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:478) at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:219) at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:278) at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:121) at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:89) at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1129) at org.hibernate.internal.SessionImpl.access$2600(SessionImpl.java:164) at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.load(SessionImpl.java:2696) at org.hibernate.internal.SessionImpl.get(SessionImpl.java:975) at org.hibernate.jpa.spi.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:1075) at org.hibernate.jpa.spi.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:1039) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:298) at com.sun.proxy.$Proxy85.find(Unknown Source) at org.springframework.data.jpa.repository.support.SimpleJpaRepository.findOne(SimpleJpaRepository.java:241) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:504) at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:489) at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:461) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:56) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136) ... 38 more Caused by: java.lang.IllegalArgumentException: Can not set java.lang.Integer field com.techprimers.jpa.springjpahibernateexample.model.Users.id to java.util.UUID at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167) at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171) at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:58) at sun.reflect.UnsafeObjectFieldAccessorImpl.get(UnsafeObjectFieldAccessorImpl.java:36) at java.lang.reflect.Field.get(Field.java:393) at org.hibernate.property.access.spi.GetterFieldImpl.get(GetterFieldImpl.java:39) ... 87 more {noformat}
But the code [The collection _teams_ is not empty.] {code:java} entityManager.find(Users.class, UUID.fromString("44af28c2-bbdb-11e7-abc4-cec278b6b50a")); {code} works well. No error.
The error seems to happen when the collection _teams_ is empty and the fetch type set to EAGER (in lazy mode no problem). In order to generate the unique identifier of collection (CollectionKey), Hibernate uses the value of UUID pass in parameter of method _find_ instead of to use the value of the referenced column (here Id) No error if we use a Query Builder, or if the collection is not empty
I reproduce the bug here: https://github.com/lecogiteur/ spring-jpa- hibernate- mysql eager - example bug See the unit tests
Best regards |
|