2010-11-13 13 views
5

Potrzebuję przechowywać niektóre dane w bazie danych MySQL przy użyciu Jpa 2/Hibernate 3.5.1. Ze względów starszych tabela, w której chcę przechowywać dane, ma złożony klucz podstawowy. Pierwsza część klucza podstawowego jest typu INTEGER (wartość auto-inkrementacji), druga część jest typu BIGINT (Long in Java-code - należy ustawić ręcznie przed utrwaleniem).Nie można ustawić ID pola java.lang.Integer na org.hibernate.id.IdentifierGeneratorHelper

I wprowadzone (na przykład kod poniżej stacktrace) połączony klucz główny za pomocą @ IdClass-przypisaniem, pierwszy klucz, część ma również szereg strategii wygenerowana @GeneratedValue (strategia = GenerationType.IDENTITY)

Gdy próbuje utrzymywać obiekt z kodem jak ten

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

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

następujące jest wyjątek:

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 

Moja jednostka klasy wygląda l IKE to:

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

Połączone-klucza podstawowego:

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-Tablica powstała z następującym stwierdzeniem:

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; 

Zmiana GenerationType do tabeli stałaby to działa , ale generowałby wartości idPartOne w krokach ~ 32.000. Niestety, inna aplikacja używa tej samej tabeli bazy danych bez JPA/Hibernate i ładnie zwiększa tę id-część w krokach co 1.

Wymagane jest, aby generowanie id odbywało się w ten sam sposób, bez względu na to, która aplikacja przechowuje dane w tej tabeli (tzn. id inkrementuje 1). Jakie byłoby najlepsze rozwiązanie, aby to osiągnąć? Podpowiedź, nie możemy zmienić drugiej aplikacji!

Każda pomoc jest naprawdę doceniana.

Thx,

Markus

+0

do 'idParOne' jest przyrostowe automatycznie, dlaczego określenie PK tabeli jako PRIMARY KEY ('idPartOne',' idPartTwo')? Czy jest możliwe, że rekord zostanie wstawiony do tej tabeli, ale z powielonym "idPartOne"? –

Odpowiedz

1

Czy to działa podczas opisywania wbudowanego 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; 
} 
Powiązane problemy