Spring JPA存储库:阻止保存更新 [英] Spring JPA repository: prevent update on save
问题描述
我的用户
数据库表如下所示:
My user
DB table looks like this:
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;
这是我的实体的字段定义:
This is the field definitions of my entity:
@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;
字段用户名
是我的关键表/实体,由我来设定它的价值。
当我需要创建另一个用户时,我在我的服务中执行此操作:
The field username
is the key of my table/entity and it's up to me to set its value.
When I need to create another user, I do this in my service:
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。这不是我想要的行为,我需要它来抛出类似重复的条目异常。
有什么方法可以预防吗?我必须自己做吗?
例如:
Anyway, if the username is already taken, the repository just do an update, because the specified identifier is not null. This is not the behaviour that I want, I need it to throw something like a duplicate entry exception. Is there any way to prevent it? Do I have to do it by myself? E.g.:
User user = this.userRepository.findOne(username);
if(user != null) {
throw new RuntimeException("Username already taken"); // FIXME - eccezione applicativa
}
推荐答案
使用默认配置时,使用 CrudRepository#save()
或 JpaRepository#save()
它将委托给 EntityManager
使用 persists()
如果是新实体,或 merge()
如果不是。
When using the default configuration, and using CrudRepository#save()
or JpaRepository#save()
it will delegate to the EntityManager
to use either persists()
if it is a new entity, or merge()
if it is not.
在使用默认值时,使用适当的方法检测实体状态(新的与否)的策略配置如下:
The strategy followed to detect the entity state, new or not, to use the appropiate method, when using the default configuration is as follows:
- 默认情况下,执行 Property-ID 检查,如果<$> c $ c> null ,那么它是一个新实体,否则不是。
- 如果实体实现
Persistable
检测将委托给实体实施的isNew()
方法。 - 有第3个选项,实施
EntityInformation
,但需要进一步自定义。
- By default, a Property-ID inspection is performed, if it is
null
, then it is a new entity, otherwise is not. - If the entity implements
Persistable
the detection will be delegated to theisNew()
method implemented by the entity. - There is a 3rd option, implementing
EntityInformation
, but further customizations are needed.
因此,在您的情况下,因为您使用的用户名为 ID
,它不是null,Repository调用最终委托给 EntityManager.merge()
而不是 persist()
。所以有两种可能的解决方案:
So in your case, as you are using the username as ID
, and it isn't null, the Repository call ends up delegating to EntityManager.merge()
instead of persist()
. So there are two possible solutions:
- 使用不同的
ID
属性,设置它为null,并使用任何自动生成方法,或 - 使用户实现
Persistable
并使用isNew ()
方法,以确定它是否是新实体。
- use a diferent
ID
property, set it to null, and use any auto-generation method, or - make User implement
Persistable
and use theisNew()
method, to determine if it is a new entity or not.
如果由于某种原因,您不想修改实体,还可以更改修改刷新模式配置的行为。默认情况下,在spring数据jpa中,休眠刷新模式设置为AUTO。你想要做的是将其更改为COMMIT,并且要更改它的属性是 org.hibernate.flushMode
。您可以通过在 @Configuration
类中覆盖 EntityManagerFactoryBean
来修改此配置。
If for some reason, you don't want to modify your entities, you can also change the behaviour modifying the flush mode configuration. By default, in spring data jpa, hibernate flush mode is set to AUTO. What you want to do is to change it to COMMIT, and the property to change it is org.hibernate.flushMode
. You can modify this configuration by overriding a EntityManagerFactoryBean
in a @Configuration
class.
如果您不想弄乱EntityManager的配置,可以使用 JpaRepository #flush()
或 JpaRepository#saveAndFlush()
方法,用于提交对数据库的挂起更改。
And if you don't want to mess the configuration of the EntityManager, you can use the JpaRepository#flush()
or JpaRepository#saveAndFlush()
methods, to commit the pending changes to the database.
这篇关于Spring JPA存储库:阻止保存更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!