![](/img/trans.png)
[英]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.