2017-08-29 19 views
5

Tôi có dòng mã sau đây:Đã bao nhiêu lần cơ sở dữ liệu được nhấn trong tiết kiệm mùa xuân DỮ LIỆU JPA (Iterable <S> thực thể)

@RequestMapping(value="/persons",method = RequestMethod.POST) 
@ResponseBody 
public ResponseEntity<List<Person>> saveUsers(@RequestBody List<Person> persons) { 
     persons = (List<Person>) userRepository.save(persons); 
     return new ResponseEntity<List<Person>>(persons, HttpStatus.OK); 
} 

Và đây là kho:

@Transactional 
public interface UserRepository extends UserBaseRepository<User> { 
} 

@NoRepositoryBean 
public interface UserBaseRepository<T extends User> extends CrudRepository<T, Long> { 
    public T findByEmail(String email); 
} 

Nó chạy tốt . Trong khi chạy mã tôi thấy các bản ghi sau.

Hibernate: insert into user (email, firstname, lastname, user_type) values (?, ?, ?, 'Person') 
Hibernate: insert into user (email, firstname, lastname, user_type) values (?, ?, ?, 'Person') 
Hibernate: insert into user (email, firstname, lastname, user_type) values (?, ?, ?, 'Person') 
Hibernate: insert into user (email, firstname, lastname, user_type) values (?, ?, ?, 'Person') 

Dường như, DataBase được nhấn 4 lần. Tôi đã thấy việc thực hiện phương thức save (iterable e), nơi vòng lặp for được chạy để lưu từng thực thể. Vì vậy, câu hỏi của tôi là:

  1. là lần truy cập DB 4 lần?
  2. nếu có, sau đó nó có thể được thực hiện trong lần truy cập 1 db (sử dụng dữ liệu Spring JPA) không? Bằng cách làm như vậy, nó sẽ cung cấp cho một tăng hiệu suất trong trường hợp chèn một số lượng lớn các hồ sơ?
+0

Có, bạn đang nhấn db 4 lần. Nếu bạn đang làm việc với các ứng dụng highload, ý tưởng tốt sẽ là sử dụng hàng loạt ngủ đông hoặc ... tạo ra các lô của riêng bạn bằng cách sử dụng đa luồng. – Reborn

+0

Nó phụ thuộc vào ý bạn bằng cách nhấn vào cơ sở dữ liệu 4 lần - bạn có thể có 4 chèn trên một kết nối, trong đó chi phí thực có khả năng tạo kết nối – farrellmr

+0

@farrellmr: Tôi cũng nghĩ như vậy. Vì vậy, giải pháp chèn các bản ghi ở trên có hiệu quả hơn so với phương thức addBatch() và executeebatch() của JDBC từ quan điểm thực hiện? –

Trả lời

4

Có, bạn đang truy vấn dữ liệu bốn lần.

Bạn có thể thực hiện chèn trong một tuyên bố lô bằng cách triển khai Hibernate Batching. Đặc biệt, hãy xem thực hiện batch inserts. Sử dụng chèn hàng loạt, bạn phải kiểm soát phiên theo cách thủ công bằng cách thực hiện cuộc gọi rõ ràng đến các phương thức flush()clear() trong phiên.

Ngoài ra, hãy xem xét việc thiết lập thích hợp Hibernate Batching Properties như kích thước hàng loạt (mặc định 5), và nếu thích hợp, chèn phép Hibernate để xếp lại thứ tự và cập nhật trước khi xây dựng các báo cáo hàng loạt:

hibernate.jdbc.batch_size = 25 
hibernate.order_inserts = true 
hibernate.order_updates = true 
+0

Tôi đã thử những gì bạn đề xuất nhưng kết quả là như nhau. 'Danh sách cuối cùng savedEntities = new ArrayList (entity.size()); \t \t int i = 0; \t \t cho (T t: thực thể) { \t \t \t savedEntities.add (persistOrMerge (t)); \t \t \t i ++; \t \t \t if (i% batchSize == 0) { \t \t \t \t // Flush một loạt chèn và giải phóng bộ nhớ. \t \t \t \t entityManager.flush(); \t \t \t \t entityManager.clear(); \t \t \t} \t \t} \t \t savedEntities trở lại; \t} \t tin T persistOrMerge (T t) { \t \t if (t.getId() == 0) { \t \t entityManager.persist (t); \t \t return t; \t \t} else { \t \t thực thể trả lạiManager.merge (t); \t \t} \t} ' –

+0

xin lỗi vì định dạng. –

1

Từ the docs on Hibernate Batching :

Hibernate vô hiệu hóa chèn hàng loạt ở cấp JDBC minh bạch nếu bạn sử dụng trình tạo mã định danh danh tính.

Vì vậy, nếu Person đang sử dụng một máy phát Identity (như trái ngược với Sequence máy phát điện hoặc TABLE máy phát điện) trạm trộn sẽ không diễn ra. Xem this section để biết thêm chi tiết về lý do tại sao lại như vậy.

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