Dữ liệu mùa xuân: "xóa bởi" được hỗ trợ?


99

Tôi đang sử dụng Spring JPA để truy cập cơ sở dữ liệu. Tôi có thể tìm thấy các ví dụ như findByName và countByName, mà tôi không phải viết bất kỳ triển khai phương thức nào. Tôi hy vọng tìm thấy các ví dụ để xóa một nhóm bản ghi dựa trên một số điều kiện.

Spring JPA có hỗ trợ xóa dạng deleteByName không? Bất kỳ con trỏ được đánh giá cao.

Trân trọng và cảm ơn.

Câu trả lời:


184

Câu trả lời không được chấp nhận (Spring Data JPA <= 1.6.x) :

@Modifyingchú thích để giải cứu. Tuy nhiên, bạn sẽ cần cung cấp hành vi SQL tùy chỉnh của mình.

public interface UserRepository extends JpaRepository<User, Long> {
    @Modifying
    @Query("delete from User u where u.firstName = ?1")
    void deleteUsersByFirstName(String firstName);
}

Cập nhật:

Trong các phiên bản hiện đại của mùa xuân dữ liệu JPA (> = 1.7.x) truy vấn nguồn gốc cho delete, removecountcác hoạt động có thể truy cập.

public interface UserRepository extends CrudRepository<User, Long> {

    Long countByFirstName(String firstName);

    Long deleteByFirstName(String firstName);

    List<User> removeByFirstName(String firstName);

}

2
@AndreyAtapin Downvote vì nó không còn là một câu trả lời hay nữa. Có thể xóa nó? Một trong những sai sót của stackoverflows là xử lý các thay đổi phiên bản / sửa lỗi liên quan đến các thư viện được đề cập.
Ben George

1
@webgeek, tôi đã từng giải quyết vấn đề này với DELETE FROM x WHERE id = ?1 or parent_id = ?1. Btw, hãy chắc chắn rằng bạn không có một loại trong parent__id(bạn có chủ ý có dấu gạch ngang thấp kép không?). Tại sao bạn sử dụng tùy chọn truy vấn gốc?
Andrey Atapin

4
Thậm chí tôi sử dụng 1.7.4, chú thích @Transactional là cần thiết trên của phương pháp truy vấn để có thành công xóa
gokhansari

40
Thông thường, trong một ứng dụng, bạn sẽ có các lớp / phương thức @ Service và những phương thức đó sẽ gọi Kho lưu trữ. Và các phương thức công khai của Dịch vụ @ phải là các phương thức được đánh dấu @ Giao dịch vì các giao dịch dựa trên Trường hợp sử dụng. Có nghĩa là một ca sử dụng cần phải cam kết hoặc khôi phục hoàn toàn. Không phải từng phương pháp Kho lưu trữ riêng lẻ. Vì vậy, VUI LÒNG KHÔNG sử dụng @ Transactional trên các phương thức Kho lưu trữ. Nhưng trên các phương thức Dịch vụ sử dụng kho lưu trữ.
user1567291

1
Tạo @Transactional tại repo có nghĩa là dịch vụ bên trong nếu bạn gọi repo nhiều lần, mỗi lần sẽ có giao dịch khác nhau, vì vậy hãy quay lại trong vòng 1 truy vấn. Nếu bạn cung cấp ở mức dịch vụ, toàn bộ chức năng của bạn sẽ được khôi phục về bất kỳ lỗi nào.
P Satish Patro

78

Bắt đầu truy vấn xóa sử dụng tên phương thức nhất định được hỗ trợ bắt đầu từ phiên bản 1.6.0.RC1 của Spring Data JPA. Các từ khóa removedeleteđược hỗ trợ. Là giá trị trả về, người ta có thể chọn giữa số hoặc danh sách các thực thể bị loại bỏ.

Long removeByLastname(String lastname);

List<User> deleteByLastname(String lastname);

7

Nếu bạn nhìn vào mã nguồn của Spring Data JPA, và đặc biệt là PartTreeJpaQuerylớp, bạn sẽ thấy nó đang cố gắng khởi tạo PartTree. Bên trong lớp đó, biểu thức chính quy sau

private static final Pattern PREFIX_TEMPLATE = Pattern.compile("^(find|read|get|count|query)(\\p{Lu}.*?)??By")

nên chỉ ra những gì được phép và những gì không.

Tất nhiên nếu bạn cố gắng thêm một phương thức như vậy, bạn sẽ thực sự thấy rằng nó không hoạt động và bạn nhận được toàn bộ stacktrace.

Tôi nên lưu ý rằng tôi đang sử dụng phiên bản 1.5.0.RELEASESpring Data JPA


6

2 cách: -

Truy vấn tùy chỉnh thứ nhất

@Modifying
@Query("delete from User where firstName = :firstName")
void deleteUsersByFirstName(@Param("firstName") String firstName);

Truy vấn JPA thứ hai theo phương thức

List<User> deleteByLastname(String lastname);

Khi bạn truy vấn theo phương thức (cách thứ 2), trước tiên nó sẽ thực hiện một lệnh gọi

select * from user where last_name = :firstName

Sau đó, nó sẽ tải nó trong một Danh sách Sau đó, nó sẽ gọi xóa từng id một

delete from user where id = 18
delete from user where id = 19

Đầu tiên tìm nạp danh sách đối tượng, sau đó vòng lặp for để xóa từng id một

Tuy nhiên, tùy chọn đầu tiên (truy vấn tùy chỉnh),

Nó chỉ là một truy vấn duy nhất Nó sẽ xóa bất cứ nơi nào giá trị tồn tại.

Đi qua liên kết này quá https://www.baeldung.com/spring-data-jpa-deleteby


1
Cảm ơn bạn về thông tin!
tò mò 1

2

Nếu bạn sử dụng các phương pháp xóa được xác định trước do Spring JPA cung cấp trực tiếp thì hai truy vấn dưới đây sẽ được thực thi bởi khung.

  • Đầu tiên thu thập dữ liệu (như id và cột khác) bằng cách thực hiện truy vấn chọn với mệnh đề xóa truy vấn where.

  • sau đó sau khi nhận được resultSet của truy vấn đầu tiên, các truy vấn xóa thứ hai sẽ được thực thi cho tất cả id (từng cái một)

    Lưu ý: Đây không phải là cách được tối ưu hóa cho ứng dụng của bạn vì nhiều truy vấn sẽ được thực thi cho một truy vấn xóa MYSQL.

Đây là một cách khác được tối ưu hóa để xóa mã truy vấn vì chỉ một truy vấn xóa sẽ thực thi bằng cách sử dụng các phương pháp tùy chỉnh bên dưới.



@NamedNativeQueries({

@NamedNativeQuery(name = "Abc.deleteByCreatedTimeBetween",
            query = "DELETE FROM abc WHERE create_time BETWEEN ?1 AND ?2")
    ,

    @NamedNativeQuery(name = "Abc.getByMaxId",
            query = "SELECT max(id) from abc")
})

@Entity
public class Abc implements Serializable {

}

@Repository
public interface AbcRepository extends CrudRepository {

    int getByMaxId();

    @Transactional
    @Modifying
    void deleteByCreatedTimeBetween(String startDate, String endDate);
}

1

Hãy cẩn thận khi bạn sử dụng truy vấn dẫn xuất để xóa hàng loạt. Nó không phải là những gì bạn mong đợi: DeleteExecution


Chào. Nếu bạn đang chỉ ra RBAR (hàng theo hàng đau đớn), bạn có thể thêm nó vào câu trả lời của mình không? (và tôi sẽ ủng hộ). Tôi đang đoán những gì bạn đang chỉ ra ở đây.
granadaCoder

0

Có, phương thức deleteBy được hỗ trợ Để sử dụng nó, bạn cần chú thích phương thức bằng @Transactional

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.