繁体   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