2013-04-19 26 views
5

Tôi thường xuyên viết các bài kiểm tra đơn vị mã phụ thuộc cơ sở dữ liệu của tôi bằng cơ sở dữ liệu HSQL trong bộ nhớ làm cơ sở dữ liệu thử nghiệm. Gần đây tôi đã quyết định nâng cấp từ 1.8.1.3 lên 2.2.9 để tận dụng lợi thế của ROW_NUMBER() hỗ trợ đã được thêm vào trong nhánh phát hành 2.x.Kiểm tra đơn vị mã dựa trên Hibernate trên đầu trang của hsqldb 1.8.1.3 không còn hoạt động trên hsqldb 2.2.9

Dường như, theo một cách nào đó, phiên bản mới nghiêm ngặt hơn phiên bản cũ. Sử dụng Hibernate (3.6.10) làm ORM, tôi có thể tạo một đối tượng Configuration để tạo SessionFactory đầu tiên, sử dụng để điền dữ liệu thử nghiệm, sau đó sử dụng Configuration cho lớp đang thử nghiệm, tạo ra nó SessionFactory để làm một lựa chọn. Với hsqldb 1.8.1.3, không sao cả. Với 2.2.9, các khối chọn bên trong mã hsqldb. Bên dưới là SSCCE chứng minh điều này:

public void testTwoSessionFactories() throws Exception { 
    boolean withTx = false; 

    AnnotationConfiguration config = new AnnotationConfiguration().addAnnotatedClass(Entity.class); 
    config.setProperty("hibernate.hbm2ddl.auto", "create"); 
    config.setProperty(Environment.DIALECT, HSQLDialect.class.getName()); 
    config.setProperty(Environment.DRIVER, jdbcDriver.class.getName()); 
    config.setProperty(Environment.URL, "jdbc:hsqldb:mem:testDB"); 
    config.setProperty(Environment.USER, "SA"); 
    config.setProperty(Environment.PASS, ""); 

    SessionFactory sessionFactory1 = config.buildSessionFactory(); 
    Session session = sessionFactory1.openSession(); 

    Transaction tx = null; 
    if (withTx) 
     tx = session.beginTransaction(); 

    session.save(new Entity("one")); 

    if (withTx) 
     tx.commit(); 

    session.flush(); 
    session.close(); 

    config.setProperty("hibernate.hbm2ddl.auto", ""); 
    SessionFactory sessionFactory2 = config.buildSessionFactory(); 
    Session session2 = sessionFactory2.openSession(); 
    List entities = session2.createCriteria(Entity.class).list(); 
    session2.close(); 
} 

Lưu ý withTx boolean. Với HSQLDB 1.8.1.3, tôi có thể chạy mã này với withTx đúng hoặc sai, và nó sẽ ổn. Với HSQLDB 2.2.9, withTxphải được thiết lập là true, nếu không sợi bị chặn trong các cuộc gọi .list() với chồng sau:

Unsafe.park(boolean, long) line: not available [native method] 
LockSupport.park(Object) line: not available  
CountDownLatch$Sync(AbstractQueuedSynchronizer).parkAndCheckInterrupt() line: not available 
CountDownLatch$Sync(AbstractQueuedSynchronizer).doAcquireSharedInterruptibly(int) line: not available 
CountDownLatch$Sync(AbstractQueuedSynchronizer).acquireSharedInterruptibly(int) line: not available 
CountDownLatch.await() line: not available 
CountUpDownLatch.await() line: not available  
Session.executeCompiledStatement(Statement, Object[]) line: not available 
Session.execute(Result) line: not available 
JDBCPreparedStatement.fetchResult() line: not available 
JDBCPreparedStatement.executeQuery() line: not available  
BatchingBatcher(AbstractBatcher).getResultSet(PreparedStatement) line: 208 
CriteriaLoader(Loader).getResultSet(PreparedStatement, boolean, boolean, RowSelection, SessionImplementor) line: 1953 
CriteriaLoader(Loader).doQuery(SessionImplementor, QueryParameters, boolean) line: 802 
CriteriaLoader(Loader).doQueryAndInitializeNonLazyCollections(SessionImplementor, QueryParameters, boolean) line: 274 
CriteriaLoader(Loader).doList(SessionImplementor, QueryParameters) line: 2542 
CriteriaLoader(Loader).listIgnoreQueryCache(SessionImplementor, QueryParameters) line: 2276 
CriteriaLoader(Loader).list(SessionImplementor, QueryParameters, Set, Type[]) line: 2271  
CriteriaLoader.list(SessionImplementor) line: 119 
SessionImpl.list(CriteriaImpl) line: 1716 
CriteriaImpl.list() line: 347 
EntityTest.testTwoSessionFactories() line: 46 

gì thay đổi trong HSQLDB giữa 1.8.1.3 và 2.2.9 mà đòi hỏi mã này để thực hiện lưu trong giao dịch và tôi có thể tắt nó không?

+0

Có thể bạn nên yêu cầu những người phát triển HSQLDB. –

+0

Mọi tương tác cơ sở dữ liệu phải được thực hiện bên trong một giao dịch. Đó là những gì tài liệu Hibernate đề xuất. Tôi chỉ đơn giản là sửa lỗi và đảm bảo bạn luôn sử dụng giao dịch. Ngoài ra, tại sao bạn sử dụng hai nhà máy phiên khác nhau? Không có lý do để làm điều đó. Nhà máy phiên là một đối tượng hạng nặng cần được tạo một lần và cho tất cả. 1 cho thử nghiệm đơn vị rõ ràng. –

+0

@JBNizet Re: các giao dịch, trong mã sản xuất Tôi luôn làm điều đó, nhưng trong thử nghiệm thiết lập mã tôi looser bởi vì tôi nghĩ rằng nó chỉ thêm lộn xộn để kiểm tra. Không tệ đến mức tôi không thể thay đổi nó được! – sharakan

Trả lời

8

HSQLDB 1.8.x sử dụng READ UNCOMMITTED cho các hàng đã được thêm hoặc thay đổi bởi giao dịch khác.

HSQLDB 2.x sử dụng READ COMMITTED (theo mặc định) hoặc SERIALIZABLE mức cách ly. Do đó một giao dịch phải cam kết trước khi các thay đổi của nó được hiển thị. Ngoài ra còn có transaction model để xem xét.

Mặc định transaction modelLOCKS khóa bảng được sửa đổi cho đến khi giao dịch được thực hiện. Thay vào đó, bạn có thể sử dụng MVCC model, cho phép các phiên khác đọc từ bảng và sửa đổi các hàng chưa được sửa đổi. Bạn có thể sử dụng mô hình này với một số URL property.

config.setProperty(Environment.URL, "jdbc:hsqldb:mem:testDB;hsqldb.tx=mvcc"); 
+0

Nghe như vậy, tôi sẽ kiểm tra. Bất kỳ cách nào để thay đổi một thuộc tính để tôi có thể thay đổi thành READ UNCOMMITTED ở cấp độ kết nối? – sharakan

+0

ĐỌC UNCOMMITTED không được hỗ trợ trong các phiên bản mới hơn. – fredt

+0

OK, tôi đã dựa vào tính năng 'đọc' bẩn mà họ nói về [tài liệu] (http://hsqldb.org/doc/guide/sessions-chapt.html#snc_tx_tx_cc). Tôi sẽ thay đổi để sử dụng các giao dịch rõ ràng trong bài kiểm tra của tôi, cảm ơn đã chỉ cho tôi cách! – sharakan

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