JPA实体inheritance与抽象类 – ConstrainViolationException

我正在尝试使用JPA注释和抽象类来设置实体inheritance。

我们的目标是让DAO通过其扩展与基础对象一起工作,这样我们就可以通过使用不同的实体扩展,切入点和覆盖来实现相同应用程序的突变,而无需更改提供者和管理者。

示例:基本应用程序堆栈有一个DAO提供程序,它使用抽象的Company实体来持久化所有扩展Company的对象:

@Entity @Inheritance(strategy = InheritanceType.JOINED) public abstract class Company extends AbstractPersistable { @Column(unique = true) private String register_number; // ... } @Component public class CompanyProvider extends JpaProvider { // provides CRUD methods via an EntityManager } 

(JPAProvider设置供参考:)

 public abstract class JpaProvider implements JpaRepository, JpaSpecificationExecutor, QueryDslPredicateExecutor { @PersistenceContext private EntityManager em; 

应用程序A将公司扩展到CompanyDefault添加自己的列但不更改DAO。 申请B应该这样做:

 @Entity @Table(name = "company") public class CompanyDefault extends Company { private String name; } 

persistence.xml对于每个应用程序(或UnitTest)都存在一次,因此这应该定义实际实体:

   path.to.CompanyDefault   

现在创建一个公司我做了以下事情:

 @Inject private CompanyProvider companyProvider; @Test public void testAbstractCompany() { Company company = new CompanyDefault("123"); ((CompanyDefault)company).setName("test"); companyProvider.save(company); } 

令人不满意的结果是ConstraintVioloationException告诉我有一个重复的主键条目:

 javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not insert: [...CompanyDefault] at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1215) at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1148) at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1154) at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:678) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:240) at $Proxy37.persist(Unknown Source) at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:328) at ....JpaProvider.save(JpaProvider.java:287) at ....JpaProvider$$FastClassByCGLIB$$2caf68f6.invoke() at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191) at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:617) at ....CompanyProvider$$EnhancerByCGLIB$$d3a45b31.save() at ....PersonManagerTest.testAbstractCompany(PersonManagerTest.java:111) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74) at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82) at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) at org.junit.runners.ParentRunner.run(ParentRunner.java:236) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) Caused by: org.hibernate.exception.ConstraintViolationException: could not insert: [....CompanyDefault] at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96) at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66) at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2454) at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2854) at org.hibernate.action.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:71) at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:273) at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:320) at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:203) at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:129) at org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:69) at org.hibernate.event.def.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:179) at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:135) at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:61) at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:808) at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:782) at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:786) at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:672) ... 42 more Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '8' for key 'PRIMARY' at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) at java.lang.reflect.Constructor.newInstance(Constructor.java:513) at com.mysql.jdbc.Util.handleNewInstance(Util.java:406) at com.mysql.jdbc.Util.getInstance(Util.java:381) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1038) at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3563) at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3495) at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1959) at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2113) at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2693) at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2102) at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2395) at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2313) at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2298) at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2437) ... 56 more 

现在为什么hibernate试图将同一个实体保持两次?

我的设置和注释怎么样?

我们想要做什么:通过使用抽象类的扩展来保存实体?

非常感谢你的帮助!

编辑:

如果我直接创建并保存扩展对象,也会发生同样的情况:

 @Test public void testAbstractCompany() { CompanyDefault companyDefault = new CompanyDefault("123"); companyProvider.save(companyDefault); } 

编辑2 – 解决:

别介意我的文字墙,已经解决了..只是一个简单的错误复制 – 谷歌搜索结果:

显然必须使用InheritanceType.SINGLE_TABLE 。 我会尽快关闭这个。

根据编辑解决2:抱歉打扰你。