簡體   English   中英

插入新實體:Spring Data JPA 與 Hibernate 的 EntityManager

[英]Insert new entity: Spring Data JPA vs. Hibernate's EntityManager

請看下面的兩個代碼示例,我將在我的Spring Boot項目中使用它們。 它們都只做同樣的事情 - 將一個新對象添加到users表中,由User實體表示, User username定義為@Id和對email列施加的unique約束(還有一些其他列,但此處未顯示它們)簡潔)。 注意:我不能簡單地使用CrudRepository save()方法,因為如果它們都具有相同的username值,它會將現有記錄與新對象合並 相反,我需要插入一個新對象,並為重復數據持久性拋出適當的異常。

我的問題是應該給哪個選項一個幫助。 使用EntityManager ,我不需要構造 SQL 語句。 除了這個明顯的觀察之外,一種方法比另一種方法有什么優勢(特別是在性能和​​資源消耗方面)?

此外,當我閱讀有關Spring Boot數據持久性的最新書籍和教程時,它們主要關注Spring Data JPA 例如, “Spring in Action”第 5 版沒有關於 Hibernate 的EntityMnagerEntityMnager 這是否意味着直接處理Hibernate可以被視為一種“老派”並且在現代項目中通常應該避免?

選項 #1:Hibernate 的 EntityManager

@RestController
@RequestMapping(path = "/auth/register", produces = "application/json")
@Transactional
public class RegistrationController {

    @PersistenceContext
    EntityManager entityManager;

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public Map<String, String> registerNewUser(@RequestBody @Valid User newUser) {

        try {
            entityManager.persist(newUser);
            entityManager.flush();
        } catch (PersistenceException ex) {
            // parse exception to find out which constraints have been 
            // broken - either it's duplicate username, email or both
            String message = parseExceptionForConstraintNames(ex);
            throw new ResponseStatusException(HttpStatus.CONFLICT, messsage);
        }
        
        return Collections.singletonMap("message", "Success..."); 
    }

}

選項#2:來自 CrudRepository 的自定義 @Query

@RestController
@RequestMapping(path = "/auth/register", produces = "application/json")
public class RegistrationController {

    private final UsersRepository usersRepository;

    @Autowired
    public RegistrationController(UsersRepository usersRepository) {
        this.usersRepository = usersRepository;
    }

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public Map<String, String> registerNewUser(@RequestBody @Valid User newUser) {

        try {
            usersRepository.insert(newUser);
        } catch (DataIntegrityViolationException ex) {
            // parse exception to find out which constraints have been 
            // broken - either it's duplicate username, email or both
            String message = parseExceptionForConstraintNames(ex);
            throw new ResponseStatusException(HttpStatus.CONFLICT, message);
        }
        
        return Collections.singletonMap("message", "Success..."); 
    }

}
public interface UsersRepository extends CrudRepository<User, String> {

    @Modifying
    @Transactional
    @Query(nativeQuery = true, value = "INSERT INTO users (username, email) " +
            "VALUES (:#{#user.username}, :#{#user.email})")
    void insert(@Param("user") User newUser);

}

這個答案使用JPA庫VS實體管理器。

最佳實踐是不要直接使用 Repository。 controllerrepository之間使用服務層,您可以通過使用findByUsername(String username);檢查記錄是否已存在於數據庫中來實現重復條目​​的邏輯findByUsername(String username); 如果已經存在則拋出異常,否則save()對象save()到數據庫中

根據給定的要求,實體中提交的username永遠不符合@Id

為什么不能為 id 字段添加帶有一些序列生成器的顯式 id 字段,而只保留username標記為unique約束。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM