Can not set java.lang.Integer field id to org.hibernate.id.IdentifierGeneratorHelper
Asked Answered
S

1

9

I need to store some data in a MySQL-database using Jpa 2/Hibernate 3.5.1. For legacy reasons the table I want to store data in has a compound primary key. The first part of the primary key is of type INTEGER (auto-increment-value), the second part is of type BIGINT (Long in Java-code - to be set manually before persisting).

I have implemented (example code below the stacktrace) the combined primary key via the @IdClass-Annotation, the first-key-part also has a generation strategy set: @GeneratedValue(strategy = GenerationType.IDENTITY)

When trying to persist an object with code like this

...
TestData testData = new TestData("data");
testData.setIdPartTwo(2L);

entityManager.getTransaction().begin();
entityManager.persist(testData);
entityManager.getTransaction().commit();

the following exception is thrown:

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

My entity-class looks like this:

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

The combined-primary-key:

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 was created with the following statement:

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;

Changing the GenerationType to TABLE would make it work, but would generate idPartOne-values in steps of ~32.000. Unfortunately, another application uses this very same database-table without JPA/Hibernate and is nicely incrementing this id-part in steps of 1.

It is required that the id-generation is done in the same way no matter which application stores data into this table (that is, id incrementing of 1). What would be the best solution to achieve this? Hint, we cannot change the other application!

Any help is really appreciated.

Thx,

Markus

Sepulture answered 13/11, 2010 at 12:44 Comment(1)
The 'idParOne' is incremental automatically, why you define the PK of table as PRIMARY KEY(idPartOne, idPartTwo)? Is it possible that a record is inserted into this table but with duplicated 'idPartOne'?Ungraceful
S
1

Does it work when you annotate the embedded id?

@Embeddable
public class TestDataId
{
    @GeneratedValue(strategy = GenerationType.TABLE)
    private Integer idPartOne;
    private Long idPartTwo;
}

@Entity
public class TestData
{
    @EmbeddedId
    private TestDataId key;
    private String data;
}
Sproul answered 7/6, 2012 at 14:29 Comment(1)
Have the same problem, EmbeddedId wont work for me and gives me following exception: com.microsoft.sqlserver.jdbc.SQLServerException: Ein expliziter Wert für die Identitätsspalte kann nicht in der ZIFCARGOSOFT_INVOICE_ITEMS-Tabelle eingefügt werden, wenn IDENTITY_INSERT auf OFF festgelegt ist. see full exception: gist.github.com/stefanwendelmann/…Deposit

© 2022 - 2024 — McMap. All rights reserved.