我的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;
}
无论如何,如果已经使用了用户名,则存储库只会进行更新,因为指定的标识符不为null。这不是我想要的行为,我需要它抛出类似重复的条目异常。 有什么办法可以预防吗?我必须自己做吗? E.g:
User user = this.userRepository.findOne(username);
if(user != null) {
throw new RuntimeException("Username already taken"); // FIXME - eccezione applicativa
}
答案 0 :(得分:16)
使用默认配置并使用CrudRepository#save()
或JpaRepository#save()
时,如果EntityManager
是新实体,则委托persists()
使用merge()
或null
1}}如果不是。
使用默认配置时,检测实体状态(新的与否,使用适当的方法)的策略如下:
Persistable
,则检查是新实体,否则检查不是。isNew()
,则检测将委托给实体实施的EntityInformation
方法。ID
,但需要进一步自定义。因此,在您的情况下,由于您使用的用户名为EntityManager.merge()
,并且它不为空,因此存储库调用最终委派给persist()
而不是ID
。所以有两种可能的解决方案:
Persistable
属性,将其设置为null,并使用任何自动生成方法,或isNew()
并使用org.hibernate.flushMode
方法确定它是否是新实体。如果由于某种原因,您不想修改实体,还可以更改修改刷新模式配置的行为。默认情况下,在spring数据jpa中,hibernate flush模式设置为AUTO。您要做的是将其更改为COMMIT,并且要更改它的属性为EntityManagerFactoryBean
。您可以通过覆盖@Configuration
类中的JpaRepository#flush()
来修改此配置。
如果您不想弄乱EntityManager的配置,可以使用JpaRepository#saveAndFlush()
或:not()
方法将挂起的更改提交到数据库。
答案 1 :(得分:0)
我最好的猜测是,它将使您的实体分离,并且根据JPA文档,它声明当传入的对象是分离的实体时,persist方法抛出 EntityExistsException。或者在刷新持久性上下文或提交事务时的任何其他PersistenceException。
答案 2 :(得分:0)
如果userRepository扩展了CrudRepository,则也许可以使用existById(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/