2010-10-12 23 views
5

Tôi có một ứng dụng Java sử dụng Spring + Hibernate. Tôi có một giao dịch khá đơn giản mà gần đây đã bắt đầu mất REALLY khá lâu để thực thi (~ 25 giây) mặc dù nó không thực hiện bất kỳ truy vấn tối nghĩa/phức tạp nào và theo nhật ký, 25 giây đó được sử dụng trong mã của Hiberante. Trình duyệt chỉ treo ở đó đợi cho đến khi hoàn thành ...Giao dịch Spring + Hibernate mất 25 giây không làm gì cả

Giao dịch được thực hiện mặc dù chú thích, sử dụng org.springframework.orm.hibernate3.LocalSessionFactoryBean làm phiên làm việc phiên và org.springframework.orm.hibernate3.HibernateTransactionManager làm người quản lý giao dịch.

Đối với bộ nhớ cache Hibernate của tôi đang sử dụng memcached, nhưng nó không phải là một vấn đề, theo nhật ký ít nhất nó không chạm vào bộ nhớ cache trong khi chờ đợi ....

tôi ở đây nộp mảnh liên quan của các bản ghi:

[DEBUG] [2010-10-09 @ 07:25:30] [http-8080-12|HibernateTransactionManager] Found thread-bound Session [[email protected]] for Hibernate transaction 
[DEBUG] [2010-10-09 @ 07:25:30] [http-8080-12|HibernateTransactionManager] Using transaction object [org.springframework.orm.hi[email protected]35ca1808] 
[DEBUG] [2010-10-09 @ 07:25:30] [http-8080-12|HibernateTransactionManager] Creating new transaction with name [com.quebicoca.api.service.PaymentService.buy]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT 
[DEBUG] [2010-10-09 @ 07:25:30] [http-8080-12|HibernateTransactionManager] Preparing JDBC Connection of Hibernate Session [[email protected]] 
[DEBUG] [2010-10-09 @ 07:25:30] [http-8080-12|HibernateTransactionManager] Exposing Hibernate transaction as JDBC transaction [[email protected]] 
[DEBUG] [2010-10-09 @ 07:25:30] [http-8080-12|TransactionSynchronizationManager] Bound value [[email protected]] for key [[email protected]ca8b] to thread [http-8080-12] 
[DEBUG] [2010-10-09 @ 07:25:30] [http-8080-12|TransactionSynchronizationManager] Initializing transaction synchronization 
[DEBUG] [2010-10-09 @ 07:25:30] [http-8080-12|TransactionInterceptor] Getting transaction for [com.quebicoca.api.service.PaymentService.buy] 
[DEBUG] [2010-10-09 @ 07:25:30] [http-8080-12|TransactionSynchronizationManager] Retrieved value [[email protected]] for key [[email protected]] bound to thread [http-8080-12] 
[DEBUG] [2010-10-09 @ 07:25:30] [http-8080-12|HibernateTransactionManager] Found thread-bound Session [[email protected]] for Hibernate transaction 
[DEBUG] [2010-10-09 @ 07:25:30] [http-8080-12|TransactionSynchronizationManager] Retrieved value [[email protected]] for key [[email protected]ca8b] bound to thread [http-8080-12] 
[DEBUG] [2010-10-09 @ 07:25:30] [http-8080-12|HibernateTransactionManager] Using transaction object [org.springframework.orm.hi[email protected]36d0805f] 
[DEBUG] [2010-10-09 @ 07:25:30] [http-8080-12|HibernateTransactionManager] Participating in existing transaction 
[DEBUG] [2010-10-09 @ 07:25:30] [http-8080-12|TransactionInterceptor] Getting transaction for [com.quebicoca.api.service.PaymentService.buy] 
[DEBUG] [2010-10-09 @ 07:25:30] [http-8080-12|TransactionSynchronizationManager] Retrieved value [[email protected]] for key [[email protected]] bound to thread [http-8080-12] 
[DEBUG] [2010-10-09 @ 07:25:55] [http-8080-25|HashCodeKeyStrategy] Transformed key [UserOrder_holders] to hashCode [-1959252437] 
[DEBUG] [2010-10-09 @ 07:25:55] [http-8080-25|HashCodeKeyStrategy] Final cache key: [org.hibernate.cache.UpdateTimestampsCache:0:-1959252437] 
[DEBUG] [2010-10-09 @ 07:25:55] [http-8080-25|MemcachedCache] Memcache.set(org.hibernate.cache.UpdateTimestampsCache:0:-1959252437) 
[DEBUG] [2010-10-09 @ 07:25:55] [http-8080-25|SpyMemcache] MemcachedClient.set(org.hibernate.cache.UpdateTimestampsCache:0:-1959252437) 
... 
[DEBUG] [2010-10-09 @ 07:25:55] [http-8080-25|DispatcherServlet] Successfully completed request 
[DEBUG] [2010-10-09 @ 07:25:55] [http-8080-25|TransactionSynchronizationManager] Removed value [[email protected]] for key [[email protected]] from thread [http-8080-25] 
[DEBUG] [2010-10-09 @ 07:25:55] [http-8080-25|OpenSessionInViewFilter] Closing single Hibernate Session in OpenSessionInViewFilter 
[DEBUG] [2010-10-09 @ 07:25:55] [http-8080-25|SessionFactoryUtils] Closing Hibernate Session 
[DEBUG] [2010-10-09 @ 07:25:55] [http-8080-25|ExceptionTranslationFilter] Chain processed normally 
[DEBUG] [2010-10-09 @ 07:25:55] [http-8080-25|SecurityContextPersistenceFilter] SecurityContextHolder now cleared, as request processing completed 
[DEBUG] [2010-10-09 @ 07:25:56] [http-8080-12|TransactionSynchronizationManager] Retrieved value [[email protected]] for key [[email protected]] bound to thread [http-8080-12] 
[DEBUG] [2010-10-09 @ 07:25:56] [http-8080-12|TransactionSynchronizationManager] Retrieved value [[email protected]] for key [[email protected]] bound to thread [http-8080-12] 
[DEBUG] [2010-10-09 @ 07:25:56] [http-8080-12|HibernateTemplate] Found thread-bound Session for HibernateTemplate 
[DEBUG] [2010-10-09 @ 07:25:56] [http-8080-12|HashCodeKeyStrategy] Transformed key [UserOrder] to hashCode [-1966312925] 
[DEBUG] [2010-10-09 @ 07:25:56] [http-8080-12|HashCodeKeyStrategy] Final cache key: [org.hibernate.cache.UpdateTimestampsCache:0:-1966312925] 

điều cuối cùng đăng nhập trước khi khoảng cách 25 giây là:

[DEBUG] [2010-10-09 07:25:30 @] [http-8080-12 | TransactionSynchronizationManager ] Lấy giá trị [[email protected]] cho khóa [org .hibernate.impl.SessionFactoryImpl @ c4be179] liên kết với chuỗi [http-8080-12]

Tôi là người duy nhất đăng nhập trong nhật ký này, tôi tắt quyền truy cập cho tất cả mọi người ngoại trừ bản thân mình từ Apache đang chạy trước Tomcat.

Mọi ý tưởng đều được hoan nghênh.

EDIT:

thêm lớp thứ tự của tôi theo yêu cầu:

@Entity 
@Table(name = "UserOrder") 
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE) 
public class Order { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Long id; 

    @ManyToOne(optional = false) 
    private Deal deal; 
    @CollectionOfElements 
    private Map<String, Integer> holders; 
    @ManyToOne(optional = false) 
    private User user; 
    @org.hibernate.annotations.Type(type = "org.joda.time.contrib.hibernate.PersistentDateTime") 
    @Column(nullable = false) 
    private DateTime buyingDate; 
    @Column(nullable = false) 
    @Enumerated(EnumType.STRING) 
    private OrderState state; 
    private BigDecimal payedWithUserCredit; 
    @Column(nullable = false) 
    private int quantity; 
    @Column(nullable = false) 
    private String secret; 

    private boolean mailSent; 

    @Enumerated(EnumType.STRING) 
    private PaymentMethod paymentMethod; 
} 

EDIT 2:

Afeter gợi ý Spy memcached có thể có cái gì để làm, tôi quyết định quay trở lại EHCache.

Nó trở nên tồi tệ hơn (1:16 treo). Nhật ký:

[DEBUG] [2010-10-13 @ 04:28:47] [http-8080-1|HibernateTransactionManager] Triggering beforeCommit synchronization 
[DEBUG] [2010-10-13 @ 04:28:47] [http-8080-1|HibernateTransactionManager] Triggering beforeCompletion synchronization 
[DEBUG] [2010-10-13 @ 04:28:47] [http-8080-1|HibernateTransactionManager] Initiating transaction commit 
[DEBUG] [2010-10-13 @ 04:28:47] [http-8080-1|HibernateTransactionManager] Committing Hibernate transaction on Session [[email protected]] 
[DEBUG] [2010-10-13 @ 04:30:03] [http-8080-1|HibernateTransactionManager] Triggering afterCommit synchronization 
[DEBUG] [2010-10-13 @ 04:30:03] [http-8080-1|HibernateTransactionManager] Triggering afterCompletion synchronization 
[DEBUG] [2010-10-13 @ 04:30:03] [http-8080-1|TransactionSynchronizationManager] Clearing transaction synchronization 
[DEBUG] [2010-10-13 @ 04:30:03] [http-8080-1|TransactionSynchronizationManager] Removed value [[email protected]] for key [[email protected]616] from thread [http-8080-1] 
[DEBUG] [2010-10-13 @ 04:30:03] [http-8080-1|HibernateTransactionManager] Not closing pre-bound Hibernate Session [[email protected]] after transaction 
[DEBUG] [2010-10-13 @ 04:30:03] [http-8080-1|TransactionSynchronizationManager] Retrieved value [[email protected]] for key [[email protected]] bound to thread [http-8080-1] 
[DEBUG] [2010-10-13 @ 04:30:03] [http-8080-1|DriverManagerDataSource] Creating new JDBC DriverManager Connection to [jdbc:mysql://localhost/quebicoca] 
[DEBUG] [2010-10-13 @ 04:30:03] [http-8080-1|TransactionSynchronizationManager] Retrieved value [[email protected]] for key [[email protected]] bound to thread [http-8080-1] 

Tôi compeltely mất ...

+0

Do quá khứ của các thông điệp tường trình, tôi giả sử (có thể không chính xác) để truy xuất phiên giữ hoàn thành trong một khoảng thời gian hợp lý. Là một trong những lớp học của bạn, và nếu có, nó trông như thế nào? – Jeff

+0

Jeff: Không, thông điệp đó từ 'TransactionSynchronizationManager' có nghĩa là kết thúc truy xuất. Cũng Memcached có thể là một vấn đề vì 'HashCodeKeyStrategy' là một lớp từ hibernate-memcached. – axtavt

+0

Tôi đã thêm mã của Đơn đặt hàng cho Jeff. Hy vọng nó làm sáng tỏ một số vấn đề .... – Johnco

Trả lời

2

đặn nó ra!

Trong phương pháp @Transactional làm điều này tôi sẽ làm một cái gì đó như thế này:

orderDAO.save(order); 
user.addOrder(order); 

Vì vậy, thứ tự sẽ được lưu lại, và thêm vào Set của người sử dụng đơn đặt hàng.

Khi lưu được gọi, phần chèn cho đơn đặt hàng đã được đặt, nhưng không phải cho người giữ.

Khi thoát khỏi phương pháp, Hibernate sẽ đi qua tất cả các mô hình trong phiên để xem những gì khác cần phải được tiếp tục tồn tại (sẽ chỉ cho thấy UserOrder_holder còn lại). Dường như nó sẽ mất FOREVER cố gắng để con số này ra với các đơn đặt hàng của người dùng, và các giao dịch liên quan (hầu hết trong số đó được lặp đi lặp lại trong các đơn đặt hàng khác nhau). Và tôi không nói về một cơ sở dữ liệu khổng lồ, truy vấn được sử dụng để truy xuất các đơn đặt hàng sẽ chỉ trả lại 17 hàng từ cơ sở dữ liệu ... Nó chỉ là lame.

Dù sao, việc đặt quan hệ của Đơn hàng với Thỏa thuận lười biếng giải quyết được vấn đề, ít nhất là bây giờ, t có thể xuất hiện lại sau đó với nhiều Đơn hàng hơn.

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