[英]Insert new entity: Spring Data JPA vs. Hibernate's EntityManager
Please, look at the two code examples bellow which I'm going to use in my Spring Boot
project.请看下面的两个代码示例,我将在我的
Spring Boot
项目中使用它们。 They both do merely the same thing - add a new object into users
table, represented by User
entity with username
defined as @Id
and a unique
constraint imposed on email
column (there are some other columns as well, but they are not shown here for brevity).它们都只做同样的事情 - 将一个新对象添加到
users
表中,由User
实体表示, User
username
定义为@Id
和对email
列施加的unique
约束(还有一些其他列,但此处未显示它们)简洁)。 Note: I can't simply use save()
method from CrudRepository
, because it merges existing record with new object if they both have the same username
value.注意:我不能简单地使用
CrudRepository
save()
方法,因为如果它们都具有相同的username
值,它会将现有记录与新对象合并。 Instead, I need to insert a new object with appropriate exception thrown for duplicate data persistence.相反,我需要插入一个新对象,并为重复数据持久性抛出适当的异常。
My question is about which option should be given a favor.我的问题是应该给哪个选项一个帮助。 With
EntityManager
, I don't need to construct SQL statement.使用
EntityManager
,我不需要构造 SQL 语句。 Apart from that obvious observation, are there any advantages which one method may offer over the other (especially, in the matter of performance and resources consumption)?除了这个明显的观察之外,一种方法比另一种方法有什么优势(特别是在性能和资源消耗方面)?
Also, when I read latest books and tutorials about data persistence in Spring Boot
, they mainly focus on Spring Data JPA
.此外,当我阅读有关
Spring Boot
数据持久性的最新书籍和教程时,它们主要关注Spring Data JPA
。 For example, the 5th edition of "Spring in Action" has no word about Hibernate's EntityMnager
.例如, “Spring in Action”的第 5 版没有关于 Hibernate 的
EntityMnager
的EntityMnager
。 Does it mean that dealing with Hibernate
directly can be regarded as kind of "old school" and should generally be avoided in modern projects?这是否意味着直接处理
Hibernate
可以被视为一种“老派”并且在现代项目中通常应该避免?
Option #1: Hibernate's EntityManager选项 #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...");
}
}
Option #2: custom @Query from CrudRepository选项#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);
}
See this answer for Using JPA repository vs Entity Manager.见这个答案使用JPA库VS实体管理器。
Best practice is to not use Repository directly.最佳实践是不要直接使用 Repository。 use Service layer between
controller
and repository
where you can implement the logic for duplicate entries by checking if the record already exist in DB using findByUsername(String username);
在
controller
和repository
之间使用服务层,您可以通过使用findByUsername(String username);
检查记录是否已存在于数据库中来实现重复条目的逻辑findByUsername(String username);
throw exception if it already exist else save()
the object in DB如果已经存在则抛出异常,否则
save()
对象save()
到数据库中
With the given requirements, the username
filed in the entity never qualifies for the @Id
.根据给定的要求,实体中提交的
username
永远不符合@Id
。
Why can't u add an explicit id field with some sequence generator for the id filed and just keep the username
marked with unique
constraint only.为什么不能为 id 字段添加带有一些序列生成器的显式 id 字段,而只保留
username
标记为unique
约束。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.