Spring JPA存储库:阻止保存更新 [英] Spring JPA repository: prevent update on save

查看:74
本文介绍了Spring JPA存储库:阻止保存更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的用户数据库表如下所示:

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 the isNew() method implemented by the entity.
  • There is a 3rd option, implementing EntityInformation, but further customizations are needed.

source

因此,在您的情况下,因为您使用的用户名为 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 the isNew() 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆