【发布时间】:2026-02-17 16:00:01
【问题描述】:
请看下面两个代码示例,我将在我的Spring Boot 项目中使用它们。他们都只是做同样的事情——在users 表中添加一个新对象,由User 实体表示,username 定义为@Id 和unique 约束施加在email 列上(还有一些其他的列,但为简洁起见,此处未显示)。注意:我不能简单地使用来自CrudRepository 的save() 方法,因为如果它们都具有相同的username 值,它会将现有记录与新对象合并。相反,我需要插入一个带有适当异常的新对象,以实现重复数据持久性。
我的问题是应该支持哪个选项。有了EntityManager,就不用构造SQL语句了。除了这个明显的观察结果之外,一种方法比另一种方法有什么优势(特别是在性能和资源消耗方面)?
另外,当我在Spring Boot 阅读有关数据持久性的最新书籍和教程时,他们主要关注Spring Data JPA。例如,第 5 版“Spring in Action” 没有关于 Hibernate 的 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);
}
【问题讨论】:
-
一个问题的问题太多了。
标签: java spring spring-boot hibernate spring-data-jpa