Reputation: 53
I have a simple project using spring data jpa with hibernate implementation. There is an entity with composite id, which I mapped it with id-class in xml. I defined my entity like this:
public class MyEntity {
private long idA;
private String idB;
private String idC;
public MyEntity() {
super();
}
public MyEntity(long anIdA, String anIdB, String anIdC) {
super();
this.idA = anIdA;
this.idB = anIdB;
this.idC = anIdC;
}
public long getIdA() {
return idA;
}
public String getIdB() {
return idB;
}
public String getIdC() {
return idC;
}
@Override
public String toString() {
return "Entity [idA=" + idA + ", idB=" + idB
+ ", idC=" + idC + "]";
}
}
I defined idClass like this:
public class MyEntityId implements Serializable {
private static final long serialVersionUID = 9073138829628574603L;
private long idA;
private String idB;
private String idC;
public MyEntityId() {
}
public MyEntityId(long anIdA, String anIdB, String anIdC) {
this.idA = anIdA;
this.idB = anIdB;
this.idC = anIdC;
}
public long getIdA() {
return idA;
}
public String getIdB() {
return idB;
}
public String getIdC() {
return idC;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj != null && obj instanceof MyEntityId) {
MyEntityId uk = (MyEntityId) obj;
return this.idA == uk.getIdA()
&& this.idB != null ?
this.idB.equals(uk.getIdB())
: uk.getIdB() == null
&& this.idC != null ?
this.idC.equals(uk.getIdC())
: uk.getIdC() == null;
}
return false;
}
@Override
public int hashCode() {
return Objects.hash(idA, idB, idC);
}
}
My repository is this:
public interface MyEntityJpaRepository extends
JpaRepository<MyEntity, MyEntityId> {
}
And the orm.xml
<entity class="myProject.domain.MyEntity" name="MyEntity"
metadata-complete="true" access="FIELD">
<table name="tb_myentity" />
<id-class class="myproject.persistance.MyEntityId" />
<attributes>
<id name="idA">
<column name="id_a" />
</id>
<id name="idB">
<column name="id_b" />
</id>
<id name="idC">
<column name="id_c" />
</id>
</attributes>
</entity>
Now is the problem: MyEntityJpaRepository.exists(aMyEntityIdInstance) is worked well, but MyEntityJpaRepository.save(aMyEntityInstance) throws this exeption:
org.springframework.dao.InvalidDataAccessApiUsageException: Class must not be null; nested exception is java.lang.IllegalArgumentException: Class must not be null
by SimpleJpaRepository.save
I found spring Data seemed to fail to get an ID. What have I done wrong or what did I missed? Any body can help?
Edit: This is the code in which the exception happenned.
@Autowired
private MyEntityJpaRepository myProxyRepository;
....
public void append(long idA, String idB, String idC) {
assertNotNull(idB);
assertNotNull(idC);
myProxyRepository.save(new MyEntity(idA, idB, idC)); //throw exception
}
Here is the exception stack:
Caused by: java.lang.IllegalArgumentException: Class must not be null
at org.springframework.util.Assert.notNull(Assert.java:134)
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:97)
at org.springframework.beans.AbstractNestablePropertyAccessor.<init>(AbstractNestablePropertyAccessor.java:140)
at org.springframework.beans.BeanWrapperImpl.<init>(BeanWrapperImpl.java:109)
at org.springframework.data.util.DirectFieldAccessFallbackBeanWrapper.<init>(DirectFieldAccessFallbackBeanWrapper.java:39)
at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation$IdentifierDerivingDirectFieldAccessFallbackBeanWrapper.<init>(JpaMetamodelEntityInformation.java:314)
at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.getId(JpaMetamodelEntityInformation.java:152)
at org.springframework.data.repository.core.support.AbstractEntityInformation.isNew(AbstractEntityInformation.java:51)
at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.isNew(JpaMetamodelEntityInformation.java:227)
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:507)
at sun.reflect.GeneratedMethodAccessor26.invoke(Unknown Source)
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:520)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:505)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:477)
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)
Upvotes: 0
Views: 2139
Reputation: 53
Well, it's a defect of spring-data-jpa, which was fixed in 1.11.11.snapshot. Before the release version was distributed, I have to add an @IdClass annotation on the entity class.
Upvotes: 0