JPA Entity Inheritance with Abstract Classes - ConstrainViolationException

I am trying to customize Entity Inheritance with JPA annotations and abstract classes.

Our goal is to get the DAO to work with the underlying object through its extension so that we can have mutations of the same application using different entity extensions, pointcuts and overrides without having to change providers and managers.

Example: The underlying application stack has a DAO provider that uses an abstract company object to store all objects that extend the company:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Company  extends AbstractPersistable<Long> {

    @Column(unique = true)
    private String register_number;           

    // ...
}

@Component
public class CompanyProvider extends JpaProvider<Company, Long> {
// provides CRUD methods via an EntityManager
}

      

(JPAProvider Setup for reference :)

public abstract class JpaProvider<T, ID extends Serializable> implements JpaRepository<T, ID>, JpaSpecificationExecutor<T>, QueryDslPredicateExecutor<T> {

    @PersistenceContext
    private EntityManager em;

      

Appendix A extends Company to CompanyDefault by adding its own columns, but not changing the DAO. Appendix B should do the same:

@Entity
@Table(name = "company")
public class CompanyDefault  extends Company {    

    private String name;  

}

      

Persistence.xml exists once per application (or UnitTest), so this should define the actual entity:

<persistence ... >
    <persistence-unit name="persistanceUnit"  transaction-type="RESOURCE_LOCAL">

    <class>path.to.CompanyDefault</class>

    </persistence-unit>
</persistence>

      

Now, to create a company, I do the following:

@Inject
private CompanyProvider companyProvider;    

@Test
public void testAbstractCompany() {
    Company company = new CompanyDefault("123");
    ((CompanyDefault)company).setName("test");

    companyProvider.save(company);
}

      

The unsatisfactory result is a ConstraintVioloationException indicating that I have a duplicate entry for the primary key:

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(<generated>)
    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(<generated>)
    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

      

Now why does hibernate try to save the same face twice?

How about my setup and annotations?

Is this what we want to do: persisting objects using extensions to an abstract class?

Many thanks for your help!

Edit:

The same happens if I create and store the extended object directly:

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

      

Edit2 - Solved:

Pay no attention to my text wall, solved it already. Just a simple mistake copying google results:

Be sure to use InheritanceType.SINGLE_TABLE

. I will close this as soon as I can.

+1


source to share


1 answer


Solved as edit 2: Sorry to bother you.



+2


source







All Articles