2010-11-13 19 views
5

Necesito almacenar algunos datos en una base de datos MySQL usando Jpa 2/Hibernate 3.5.1. Por razones heredadas, la tabla en la que quiero almacenar datos tiene una clave primaria compuesta. La primera parte de la clave principal es de tipo INTEGER (auto-incremento-valor), la segunda parte es de tipo BIGINT (largo en código Java, se configurará manualmente antes de persistir).No se puede establecer el ID del campo java.lang.Integer en org.hibernate.id.IdentifierGeneratorHelper

He implementado (código de ejemplo por debajo de la StackTrace) la clave primaria combinada a través de la @ IdClass-Anotación, la primera-key-parte también tiene un conjunto estrategia de generación: @GeneratedValue (estrategia = GenerationType.IDENTITY)

al tratar de persistir un objeto con un código como éste

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

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

la excepción siguiente:

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 

Mi entidad de clase se ve l ike esto:

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

El combinado-clave 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-Mesa fue creado con la siguiente afirmación:

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; 

Cambio de la GenerationType de mesa sería hacer que funcione , pero generaría idPartOne-values ​​en pasos de ~ 32,000. Por desgracia, otra aplicación utiliza esta misma misma base de datos de la tabla sin JPA/Hibernate y está incrementando muy bien este id partes en pasos de 1.

Se requiere que el identificador de generación se realiza de la misma manera independientemente de la aplicación almacena datos en esta tabla (es decir, incremento de id de 1). ¿Cuál sería la mejor solución para lograr esto? Sugerencia, no podemos cambiar la otra aplicación!

Cualquier ayuda es realmente apreciada.

Thx,

Markus

+0

El 'idParOne' es incremental automáticamente, ¿por qué usted define el PK de la tabla como PRIMARY KEY ('idPartOne',' idPartTwo')? ¿Es posible que se inserte un registro en esta tabla pero con 'idPartOne' duplicado? –

Respuesta

1

¿Funciona cuando anotar el id incrustado?

@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; 
} 
Cuestiones relacionadas