[英]Spring Data JPA/Hibernate - using EntityManager for queries
[英]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 的EntityMnager
的EntityMnager
。 这是否意味着直接处理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。 在controller
和repository
之间使用服务层,您可以通过使用findByUsername(String username);
检查记录是否已存在于数据库中来实现重复条目的逻辑findByUsername(String username);
如果已经存在则抛出异常,否则save()
对象save()
到数据库中
根据给定的要求,实体中提交的username
永远不符合@Id
。
为什么不能为 id 字段添加带有一些序列生成器的显式 id 字段,而只保留username
标记为unique
约束。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.