Ho bisogno di memorizzare alcuni dati in un database MySQL usando Jpa 2/Hibernate 3.5.1. Per motivi legacy la tabella in cui voglio memorizzare i dati ha una chiave primaria composta. La prima parte della chiave primaria è di tipo INTEGER (auto-increment-value-value), la seconda parte è di tipo BIGINT (Long in Java-code - da impostare manualmente prima di persistere).Impossibile impostare l'ID campo java.lang.Integer su org.hibernate.id.IdentifierGeneratorHelper
Ho implementato (codice di esempio StackTrace) la chiave primaria combinato con il @ IdClass-annotazione, la prima chiave parte ha anche un set strategia generazione: @GeneratedValue (strategia = GenerationType.IDENTITY)
Quando si cerca di persistere un oggetto con codice come questo
...
TestData testData = new TestData("data");
testData.setIdPartTwo(2L);
entityManager.getTransaction().begin();
entityManager.persist(testData);
entityManager.getTransaction().commit();
la seguente eccezione viene generata:
javax.persistence.PersistenceException: org.hibernate.PropertyAccessException: could not set a field value by reflection setter of org.example.persistence.TestDataId.idPartOne
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1235)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1168)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1174)
at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:674)
at org.example.persistence.PersistenceTest.shouldPersistTestData(PersistenceTest.java:45)
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.testng.internal.MethodHelper.invokeMethod(MethodHelper.java:640)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:627)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:799)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1103)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:137)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:121)
at org.testng.TestRunner.runWorkers(TestRunner.java:1098)
at org.testng.TestRunner.privateRun(TestRunner.java:727)
at org.testng.TestRunner.run(TestRunner.java:581)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:315)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:310)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:272)
at org.testng.SuiteRunner.run(SuiteRunner.java:221)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:40)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:83)
at org.testng.internal.thread.ThreadUtil$CountDownLatchedRunnable.run(ThreadUtil.java:151)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
Caused by: org.hibernate.PropertyAccessException: could not set a field value by reflection setter of org.example.persistence.TestDataId.idPartOne
at org.hibernate.property.DirectPropertyAccessor$DirectSetter.set(DirectPropertyAccessor.java:151)
at org.hibernate.mapping.Component$ValueGenerationPlan.execute(Component.java:438)
at org.hibernate.id.CompositeNestedGeneratedValueGenerator.generate(CompositeNestedGeneratedValueGenerator.java:122)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:122)
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:800)
at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:774)
at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:778)
at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:668)
... 24 more
Caused by: java.lang.IllegalArgumentException: Can not set java.lang.Integer field org.example.persistence.TestDataId.idPartOne to org.hibernate.id.IdentifierGeneratorHelper$2
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:146)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:150)
at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:63)
at java.lang.reflect.Field.set(Field.java:657)
at org.hibernate.property.DirectPropertyAccessor$DirectSetter.set(DirectPropertyAccessor.java:139)
... 35 more
mio soggetto di classe sembra l ike questo:
@Entity
@IdClass(TestDataId.class)
public class TestData implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer idPartOne;
@Id
private Long idPartTwo;
private String data;
public TestData() {}
// getters and setters
// hashCode() and equals()
}
Il combinato-chiave primaria:
public class TestDataId implements Serializable {
private static final long serialVersionUID = 1L;
private Integer idPartOne;
private Long idPartTwo;
public TestDataId() {}
// getters and setters
// hashCode() and equals()
}
Test-Table è stato creato con la seguente dichiarazione:
CREATE TABLE `testdb`.`testdata`
(`idPartOne` INTEGER NOT NULL AUTO_INCREMENT,
`idPartTwo` BIGINT(20) NOT NULL DEFAULT 0,
`data` VARCHAR(45),
PRIMARY KEY(`idPartOne`, `idPartTwo`))
ENGINE = InnoDB;
Modifica della GenerationType alla tabella sarebbe farlo funzionare , ma genererebbe valori di idPartOne in passi di ~ 32.000. Sfortunatamente, un'altra applicazione utilizza questa stessa tabella di database senza JPA/Hibernate e incrementa piacevolmente questa parte di ID in step di 1.
È necessario che la generazione di ID avvenga nello stesso modo indipendentemente dall'applicazione memorizza i dati in questa tabella (ovvero, l'incremento di ID di 1). Quale sarebbe la soluzione migliore per raggiungere questo obiettivo? Indizio, non possiamo cambiare l'altra applicazione!
Qualsiasi aiuto è molto apprezzato.
Thx,
Markus
"idParOne" è incrementale automaticamente, perché si definisce il PK della tabella come PRIMARY KEY ('idPartOne',' idPartTwo')? È possibile che un record sia inserito in questa tabella ma con 'idPartOne' duplicato? –