2010-01-20 46 views
7

Tôi đang thực hiện một số truy vấn lớn trên cơ sở dữ liệu của mình với Hibernate và đôi khi tôi nhấn hết thời gian chờ. Tôi muốn tránh đặt thời gian chờ theo cách thủ công trên mọi Query hoặc Criteria.Hibernate: đặt thời gian chờ truy vấn mặc định?

Có bất kỳ tài sản nào tôi có thể cung cấp cho số AnnotationConfiguration có thể đặt mặc định có thể chấp nhận được cho tất cả các truy vấn tôi chạy không?

Nếu không, làm cách nào tôi có thể đặt giá trị thời gian chờ mặc định trên truy vấn Hibernate?

+0

Bạn đang sử dụng hồ bơi kết nối. – Bozho

+0

Yup, sử dụng C3PO – malaverdiere

Trả lời

5

JPA 2 xác định javax.persistence.query.timeout gợi ý để xác định thời gian chờ mặc định trong mili giây. Hibernate 3.5 (hiện vẫn đang trong giai đoạn thử nghiệm) sẽ hỗ trợ gợi ý này.

Xem thêm http://opensource.atlassian.com/projects/hibernate/browse/HHH-4662

+0

Tôi không quá vui mừng về việc xây dựng trên bản beta ... Có một cái nhìn tại trang web, tôi không thấy ngày phát hành dự kiến. Bạn có biết khi nào họ đang lên kế hoạch để phát hành nó? – malaverdiere

+0

Việc phát hành CR chỉ là một vài tuần đi và tôi sẽ nghĩ rằng 3,5 sẽ làm theo ngay sau đó. Sự tuân thủ JPA 2 cao trong danh sách ưu tiên, do đó, không có rủi ro là vấn đề sẽ nằm trong bảng. – Hardy

+0

Thời gian chờ này đang hoạt động trong trường hợp đó, khi truy vấn bị bế tắc? – Laszlo

1

Dưới đây là một vài cách sau:

  • Sử dụng một nhà máy hoặc phương pháp lớp cơ sở để tạo ra tất cả các truy vấn và thiết lập thời gian chờ trước khi trở về đối tượng Query
  • Tạo phiên bản của riêng bạn org.hibernate.loader. Trình tải và đặt thời gian chờ trong doQuery
  • Sử dụng AOP, ví dụ: Spring, để trả về một proxy cho Session; thêm lời khuyên cho nó mà kết thúc tốt đẹp các phương pháp createQuery và thiết lập thời gian chờ trên đối tượng truy vấn trước khi trở về nó
+0

Tôi đã nghĩ đến việc thực hiện tùy chọn đầu tiên bạn đưa ra lúc đầu, nhưng tôi nghĩ "chắc chắn, Hibernate cung cấp một cách để tránh điều này!" Về Loader, tôi không quá vui mừng về việc tạo ra một cái mới đầy đủ. Nhưng tôi nghĩ rằng có lẽ tôi có thể mở rộng' BasicLoader'. Điều này là, tôi không thấy một 'doQuery' trong API đó: https://www.hibernate.org/hib_docs/v3/api/org/hibernate/loader/Loader.html Vì vậy, tôi sẽ phải ghi đè phương thức nào? Tôi đoán 'doList',' getResultSet' , 'preparQueryStatement' và' scroll' Tôi có đúng không? – malaverdiere

+0

Tôi có thể sai nhưng tôi không nghĩ rằng Hibernate cho phép bạn móc vào bộ tải theo cách đó.Tôi đã sao chép bộ tải ngủ đông từ nguồn vào dự án của tôi bằng cách sử dụng cùng một gói như Hibernate , vì các lớp của tôi ở phía trước Hibernate trong classpath, được sử dụng, nhược điểm duy nhất là bạn phải làm điều đó mỗi khi bạn nâng cấp Hibernate, nhưng nếu bạn có thể vào đối tượng PreparedStatement trước khi qu ery chạy, bạn có thể gọi setQueryTimeout, do đó, PrepareQueryStatement có thể là đặt cược tốt nhất của bạn. –

3

JDBC có cơ chế này được đặt tên Query Timeout, bạn có thể gọi phương thức của đối tượng setQueryTime java.sql.Statement để kích hoạt thiết lập này.

Hibernate không thể thực hiện việc này theo cách thống nhất.

Nếu ứng dụng của bạn truy xuất lại kết nối JDBC vi java.sql.DataSource, câu hỏi có thể được giải quyết dễ dàng.

chúng tôi có thể tạo một DateSourceWrapper để kết nối proxy mà làm setQueryTimeout cho mỗi tuyên bố nó tạo ra.

Mã ví dụ dễ đọc, tôi sử dụng một số lớp học sử dụng lò xo để trợ giúp điều này.

public class QueryTimeoutConfiguredDataSource extends DelegatingDataSource { 

private int queryTimeout; 

public QueryTimeoutConfiguredDataSource(DataSource dataSource) { 
    super(dataSource); 
} 

// override this method to proxy created connection 
@Override 
public Connection getConnection() throws SQLException { 
    return proxyWithQueryTimeout(super.getConnection()); 
} 

// override this method to proxy created connection 
@Override 
public Connection getConnection(String username, String password) throws SQLException { 
    return proxyWithQueryTimeout(super.getConnection(username, password)); 
} 

private Connection proxyWithQueryTimeout(final Connection connection) { 
    return proxy(connection, new InvocationHandler() { 
     //All the Statement instances are created here, we can do something 
     //If the return is instance of Statement object, we set query timeout to it 
     @Override 
     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
      Object object = method.invoke(connection, args); 
      if (object instanceof Statement) { 
       ((Statement) object).setQueryTimeout(queryTimeout); 
      } 
      return object; 
     }); 
} 

private Connection proxy(Connection connection, InvocationHandler invocationHandler) { 
    return (Connection) Proxy.newProxyInstance(
      connection.getClass().getClassLoader(), 
      ClassUtils.getAllInterfaces(connection), 
      invocationHandler); 
} 

public void setQueryTimeout(int queryTimeout) { 
    this.queryTimeout = queryTimeout; 
} 

}

Bây giờ chúng ta có thể sử dụng QueryTimeoutConfiguredDataSource này để bao bọc của bạn tồn tại DataSource để thiết lập truy vấn Timeout mỗi khi Báo cáo minh bạch!

mùa xuân cấu hình file:

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> 
    <property name="dataSource"> 
     <bean class="com.stackoverflow.QueryTimeoutConfiguredDataSource"> 
      <constructor-arg ref="dataSource"/> 
      <property name="queryTimeout" value="1" /> 
     </bean> 
    </property> 
</bean> 
0

Đối với thiết lập giá trị timeout toàn cầu ở mức truy vấn - Thêm bên dưới để tập tin cấu hình.

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> 
    <property name="dataSource" ref="dataSource"></property> 
    <property name="queryTimeout" value="60"></property> 
</bean> 

Để đặt giá trị thời gian chờ toàn cầu ở mức giao dịch (INSERT/UPDATE) - Thêm tệp bên dưới vào tệp cấu hình.

<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
    <property name="entityManagerFactory" ref="myEmf" /> 
    <property name="dataSource" ref="dataSource" /> 
    <property name="defaultTimeout" value="60" /> 
    <property name="jpaDialect"> 
     <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" /> 
    </property> 
</bean> 
+0

Tôi gặp lỗi khi tạo maven, tôi đã chỉ ra truy vấn tại đây Bạn có thể trợ giúp: http://stackoverflow.com/questions/41613160/default-query-timeout-is-causing-exception-in- bài kiểm tra tích hợp – Pavanraotk

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