2010-11-13 19 views
5

Tôi cần lưu trữ một số dữ liệu trong cơ sở dữ liệu MySQL bằng Jpa 2/Hibernate 3.5.1. Vì lý do kế thừa, bảng tôi muốn lưu trữ dữ liệu có khóa chính ghép. Phần đầu tiên của khóa chính là kiểu INTEGER (giá trị gia tăng tự động), phần thứ hai là kiểu BIGINT (Dài trong mã Java - được đặt thủ công trước khi tồn tại).Không thể đặt id trường java.lang.Integer thành org.hibernate.id.IdentifierGeneratorHelper

tôi đã thực hiện (ví dụ mã bên dưới stacktrace) khóa chính kết hợp thông qua @ IdClass-chú thích, các-key phần đầu tiên cũng có một bộ chiến lược thế hệ: @GeneratedValue (chiến lược = GenerationType.IDENTITY)

Khi cố gắng để tồn tại một đối tượng với mã như thế này

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

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

các ngoại lệ sau đây được ném:

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 

thực thể lớp tôi trông l ike này:

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

Các kết hợp-chính-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-Bảng được tạo ra với các tuyên bố sau:

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; 

Thay đổi GenerationType để TABLE sẽ làm cho nó hoạt động , nhưng sẽ tạo idPartOne-giá trị trong các bước của ~ 32.000. Thật không may, một ứng dụng khác sử dụng bảng cơ sở dữ liệu rất giống nhau này mà không có JPA/Hibernate và độc đáo gia tăng phần id này theo các bước 1.

Việc tạo id được thực hiện theo cùng một cách bất kể ứng dụng nào lưu trữ dữ liệu vào bảng này (có nghĩa là, tăng id của 1). Điều gì sẽ là giải pháp tốt nhất để đạt được điều này? Gợi ý, chúng tôi không thể thay đổi ứng dụng khác!

Bất kỳ trợ giúp nào thực sự được đánh giá cao.

Thx,

Markus

+0

'idParOne' được gia tăng tự động, tại sao bạn xác định PK của bảng là PRIMARY KEY ('idPartOne',' idPartTwo')? Có thể là một bản ghi được chèn vào bảng này nhưng với 'idPartOne' trùng lặp? –

Trả lời

1

Liệu nó làm việc khi bạn chú thích id nhúng?

@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; 
} 
Các vấn đề liên quan