![](/img/trans.png)
[英]Spring Jpa Data Repository save (update) with LinkedEntity for ManyToMany relationship
[英]Spring JPA repository: prevent update on save
我的user
數據庫表如下所示:
CREATE TABLE user (
username VARCHAR(32) PRIMARY KEY,
first_name VARCHAR(256) NOT NULL,
last_name VARCHAR(256) NOT NULL,
password VARCHAR(32) NOT NULL,
enabled BOOL
) ENGINE = InnoDB;
這是我的實體的字段定義:
@Entity
public class User implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(nullable = false)
private String username;
@Column(nullable = false)
private String firstName;
@Column(nullable = false)
private String lastName;
@Column(nullable = false)
private String password;
字段username
是我的表/實體的密鑰,由我來設置其值。 當我需要創建另一個用戶時,我在我的服務中執行此操作:
public User insertUserImpl(String username, String firstName, String lastName) {
Assert.hasText(username);
Assert.hasText(firstName);
Assert.hasText(lastName);
String password = UUID.randomUUID().toString().substring(0, 4); // temp
User user = new User(username, password);
user.setFirstName(firstName);
user.setLastName(lastName);
user.setEnabled(false);
this.userRepository.save(user);
// FIXME - assegnare un ruolo
return user;
}
無論如何,如果已經使用了用戶名,則存儲庫只會進行更新,因為指定的標識符不為空。 這不是我想要的行為,我需要它拋出類似重復的條目異常。 有什么辦法可以預防嗎? 我必須自己做嗎? 例如:
User user = this.userRepository.findOne(username);
if(user != null) {
throw new RuntimeException("Username already taken"); // FIXME - eccezione applicativa
}
當使用默認配置,並使用CrudRepository#save()
或JpaRepository#save()
,它將委托給EntityManager
,如果它是新實體則使用CrudRepository#save()
persists()
如果不是則使用merge()
。
在使用默認配置時,遵循以下策略來檢測實體狀態(新的或不是新的)以使用適當的方法如下:
null
,則它是新實體,否則不是。 Persistable
則檢測將委托給實體實現的isNew()
方法。 EntityInformation
,但需要進一步的自定義。 因此,在您的情況下,當您使用用戶名作為ID
,並且它不為空時,Repository調用最終委托給EntityManager.merge()
而不是persist()
。 所以有兩種可能的解決方案:
ID
屬性,將其設置為null,並使用任何自動生成方法,或 Persistable
並使用isNew()
方法確定它是否是新實體。 如果由於某種原因,您不想修改實體,還可以更改修改刷新模式配置的行為。 默認情況下,在spring數據jpa中,hibernate flush模式設置為AUTO。 你想要做的是將它更改為COMMIT,並且要更改它的屬性是org.hibernate.flushMode
。 您可以通過覆蓋@Configuration
類中的EntityManagerFactoryBean
來修改此配置。
如果您不想弄亂EntityManager的配置,可以使用JpaRepository#flush()
或JpaRepository#saveAndFlush()
方法將掛起的更改提交到數據庫。
而不是this.userRepository.save(用戶),你可以嘗試this.userRepository.saveAndFlush(用戶)
我最好的猜測是,它將使您的實體分離,並且根據JPA文檔,它聲明當傳入的對象是分離的實體時,persist方法拋出EntityExistsException。 或者在刷新持久性上下文或提交事務時的任何其他PersistenceException。
如果userRepository擴展CrudRepository,可以使用existsById(ID primaryKey)來測試它:
if(userRepository.existsById(username)){
//Throw your Exception
} else {
this.userRepository.save(user);
}
請參閱https://docs.spring.io/spring-data/jpa/docs/current/reference/html/
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.