spring数据存储库无法使用idClass保存实体

时间:2018-03-19 11:42:00

标签: java spring spring-data-jpa composite-primary-key

我有一个使用spring数据jpa和hibernate实现的简单项目。有一个具有复合id的实体,我用xml中的id-class映射它。 我这样定义了我的实体:

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 + "]";
    }
}

我像这样定义了idClass:

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);
    }

}

我的存储库是这样的:

public interface MyEntityJpaRepository extends
        JpaRepository<MyEntity, MyEntityId> {
}

和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>

现在是问题所在: MyEntityJpaRepository.exists(aMyEntityIdInstance)运行良好,但是 MyEntityJpaRepository.save(aMyEntityInstance)抛出此异常:

org.springframework.dao.InvalidDataAccessApiUsageException:Class不能为null;嵌套异常是java.lang.IllegalArgumentException:Class不能为null

通过SimpleJpaRepository.save

我发现Spring数据似乎无法获得ID。 我做错了什么或者我错过了什么? 任何人都可以帮忙吗?

编辑: 这是发生异常的代码。

    @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
    }

这是异常堆栈:

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)

1 个答案:

答案 0 :(得分:0)

嗯,这是spring-data-jpa的缺陷,已在1.11.11.snapshot中修复。在发布版本之前,我必须在实体类上添加@IdClass注释。