2011-12-01 78 views
5

Tôi đang cố gắng triển khai tính bền vững của một số đối tượng Java thông qua ánh xạ Hibernate tới bảng MySQL. Khi tôi cam kết, tôi nhận được thông báo rằng 'Cập nhật hàng loạt đã trả về số hàng không mong đợi từ bản cập nhật [0]; số hàng thực tế: 0; dự kiến: 1 '.DÀI làm khóa chính trong ánh xạ Hibernate tới MySQL

Giả thuyết của tôi là vấn đề là do có một số long trong Java POJO mà tôi muốn sử dụng làm khóa chính trong bảng MySQL. Vì tôi không thể sử dụng datatype LONG làm khóa chính của tôi trong bảng MySQL (ERROR 1170: BLOB/TEXT cột 'id' được sử dụng trong đặc tả khóa không có độ dài khóa) Tôi kết luận từ một số googling và post rằng BIGINT sẽ phù hợp ánh xạ cho long. Tuy nhiên nó không được cập nhật.

Bài kiểm tra POJO Person của tôi rất đơn giản. Nó có 3 trường: id (long), firstname (String), lastname (String) với các setters và getters, v.v.

Tôi làm bản đồ ngủ đông trong xml (person.hbm.xml) về cơ bản trông giống như (trừ đi tiêu đề):

<hibernate-mapping> 
    <class name="hibernatetest.Person" table="hibernatetest"> 
    <id name="id" type="long" column="id" > 
    <generator class="native"/> 
    </id> 

    <property name="firstname"> 
    <column name="firstname" /> 
    </property> 
    <property name="lastname"> 
    <column name="lastname"/> 
    </property> 
</class> 
</hibernate-mapping> 

My đoạn mã java thực tế đó là nghĩa vụ để tiết kiệm hoặc cập nhật các bản ghi rất đơn giản:

Transaction tr = session.beginTransaction();    
Person person = new Person(1,"John","Doe"); 
session.saveOrUpdate(person); 
tr.commit(); 

Và đây là điều mà, tất cả điều này chỉ hoạt động tốt nếu tôi thay đổi loại id đến một int (số nguyên) trong đối tượng Person và trong bảng MySQL. Tuy nhiên, tôi không có tùy chọn đó cho các đối tượng thực sự mà tôi muốn tồn tại nên câu hỏi là; tôi đang làm gì sai hoặc tôi nên làm gì để làm cho nó hoạt động? Cảm ơn.

THÊM stacktrace:

Hibernate: update hibernatetest set firstname=?, lastname=? where id=? 
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1 
    at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:81) 
    at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:73) 
    at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:57) 
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3006) 
    at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2908) 
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3237) 
    at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:113) 
    at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:273) 
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:265) 
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:187) 
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337) 
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50) 
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1082) 
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:317) 
    at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101) 
    at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:175) 
    at com.hibernate.test.TestMain.main(TestMain.java:38) 
nested transactions not supported 

UPDATE: OK, tôi cuối cùng đã làm việc nó ra. Tôi đã thay đổi lớp máy phát điện hibernate từ 'native' thành 'assigned' và bây giờ nó hoạt động như mong đợi. Vì vậy, bây giờ là lập bản đồ ngủ đông trông giống như:

<hibernate-mapping> 
    <class name="hibernatetest.Person" table="hibernatetest"> 
    <id name="id" type="long" column="id" > 
    <generator class="assigned"/> 
    </id> 

    <property name="firstname"> 
    <column name="firstname" /> 
    </property> 
    <property name="lastname"> 
    <column name="lastname"/> 
    </property> 
</class> 
</hibernate-mapping> 

Phải thừa nhận tôi không biết ý nghĩa của tham số đó (sao chép từ một nơi nào) và không hề biết nó có thể gây ra nhiều đau đầu này. Tìm thấy điều này explanation đó là khá hữu ích.

Dường như tôi không có đủ thông tin để trả lời các câu hỏi của riêng tôi vì vậy tôi đoán rằng nó sẽ vẫn mở hoặc nếu ai đó cung cấp câu trả lời trống, tôi sẽ chấp nhận nó. Cảm ơn.

+0

bạn có thể đăng toàn bộ stacktrace, dài và BIGINT nên hoạt động tốt, tôi đã sử dụng nó cá nhân không có vấn đề tìm thấy, xin vui lòng chia sẻ stacktrace của bạn – mprabhat

+0

Định nghĩa kiểu cột db của bạn là gì? Và loại thuộc tính id của bạn? Dù sao, Bigint cho cột, và Long cho thuộc tính java là hoàn toàn. – polypiel

+0

@mprabhat Done. Nó có một thông báo nói rằng 'giao dịch lồng nhau không được hỗ trợ' mà tôi không thấy trước đây. Không biết ý nghĩa của nó là gì? – hgus1294

Trả lời

5

Khi bạn sử dụng phương pháp saveOrUpdate()ngủ đông bắn truy vấn chèn nếu id của đối tượng là nullupdate nếu nó là bất kỳ giá trị khác. Tôi có thể xem mã, Person person = new Person(1,"John","Doe"); đặt id thành 1 và gọi phương thức saveOrUpdate(). Tôi giả sử không có mục nhập cho id 1 và do đó lỗi được ném.

Để làm cho nó hoạt động, bạn cần thực hiện các thay đổi bên dưới.

  1. Thay đổi Loại id trong người để Long từ long (Lớp wrapper để nó có thể hỗ trợ null).

  2. Viết hàm tạo new Person("John","Doe"); và lưu đối tượng đó.

Bạn không nên giữ <generator class="assigned"/> cho dữ liệu giao dịch. Thay vào đó, bạn nên gắn bó với số native khi bạn đang cố gắng trước tiên.

Tôi cảm thấy đây là một cách sạch hơn để giải quyết vấn đề ban đầu của bạn, mặc dù bạn đã tìm thấy giải pháp thay thế.

+0

Cảm ơn bạn. Bạn đúng trong giả định rằng không có bản ghi nào trước đó với 'id' = 1 trước' SaveOrUpdate'. Tôi đã cố gắng để thay đổi loại lớp để 'Long' theo đề nghị của bạn nhưng nó reverts trở lại cùng một lỗi nếu tôi đặt máy phát điện để' native'. Tôi không hiểu bạn điểm thứ hai, nơi bạn bỏ qua 'id' từ nhà xây dựng? 'Id' không phải là id được tạo tự động vì vậy tôi cần có thể đặt nó thành một giá trị cụ thể. – hgus1294

+0

Tôi có nghĩa là để cho DB của bạn chọn ID và không mã cứng id để được trong khi tiết kiệm. Chọn từ các tùy chọn [ở đây] (http://docs.jboss.org/hibernate/core/3.3/reference/en/html/mapping.html#mapping-declaration-id) về cách thực hiện. – ManuPK

+0

OK, đã hiểu. Trong kịch bản thực tế của tôi, 'id' được cung cấp từ một dịch vụ bên ngoài và cần phải được duy trì như vậy vì vậy tôi không thể để cho db quyết định. Nếu tôi chỉ thay đổi kiểu lớp thành 'Long' và giữ một hàm tạo có một' Long', tôi nhận được ngoại lệ ban đầu. Điều đó đúng như mong đợi hay tôi đã hiểu lầm điều gì đó khác? Bạn đã đề cập đến một rủi ro với máy phát điện = 'được giao' cho các giao dịch. Rủi ro là gì? – hgus1294

Các vấn đề liên quan