使用Spring Repo更新OneToOne的列

时间:2016-03-02 18:51:02

标签: java spring spring-mvc spring-data

我的Spring Boot应用程序中有两个实体:

用户:

public class User implements java.io.Serializable, UserDetails  {
@GenericGenerator(name = "generator", strategy = "foreign", parameters = @Parameter(name = "property", value = "person") )
@Id
@GeneratedValue(generator = "generator")

@Column(name = "person_id", unique = true, nullable = false)
public int getPersonId() {
    return this.personId;
}

public void setPersonId(int personId) {
    this.personId = personId;
}

@OneToOne(fetch = FetchType.LAZY)
@PrimaryKeyJoinColumn
public Person getPerson() {
    return this.person;
}

public void setPerson(Person person) {
    this.person = person;
}

    @Column(name = "email", unique = true, nullable = false, length = 50)
public String getEmail() {
    return this.email;
}

public void setLoginVersuche(int loginVersuche) {
    this.loginVersuche = loginVersuche;
}

@Column(name ="loginVersuche")
public int getLoginVersuche() {
    return loginVersuche;
}
...omitted code...

}

public class Person implements java.io.Serializable {

@Id
@GeneratedValue(strategy = IDENTITY)

@Column(name = "idPerson", unique = true, nullable = false)
public Integer getIdPerson() {
    return this.idPerson;
}

public void setIdPerson(Integer idPerson) {
    this.idPerson = idPerson;
}

@OneToOne(fetch = FetchType.LAZY, mappedBy = "person")
public User getUser() {
    return this.user;
}

public void setUser(User user) {
    this.user = user;
}
...omitted code...
}

我有我的DAO:

@Repository
public interface UserDAO extends CrudRepository<User, Integer>{
    User findByEmail(String user);
}

现在我想更新身份验证中的字段。为此,我要求User对象(电子邮件是唯一的)并设置字段。在此之后我想更新db:

中的对象
User userByDB = userDAO.findByEmail(username);    
userByDB.setLoginVersuche(userByDB.getLoginVersuche()+1);
userDAO.save(userByDB);

它只是不更新​​db中的数据字段,但我也没有收到任何错误。是否与用户外键中的主键有关?

UPDATE-1

@Transactional
    @Modifying
    @Query("update User u set u.loginVersuche = u.loginVersuche+1, u.gesperrt = ?1 where u.email = ?2")
    public int incrementLoginVersuche(boolean gesperrt, String email);

UPDATE-2

  

23:51:43.181 TRACE org.springframework.transaction.support.TransactionSynchronizationManager - 初始化事务同步   23:51:43.182 TRACE org.springframework.transaction.interceptor.TransactionInterceptor - 获取[org.springframework.data.jpa.repository.support.SimpleJpaRepository.incrementLoginVersuche]的事务   23:51:43.183 DEBUG org.springframework.orm.jpa.EntityManagerFactoryUtils - 打开JPA EntityManager   23:51:43.184 TRACE org.hibernate.internal.SessionFactoryImpl $ SessionBuilderImpl - 打开Hibernate会话。 tenant = null,owner = land.hibernate.jpa.internal.EntityManagerImpl@71dfe394   23:51:43.184 TRACE org.hibernate.internal.SessionImpl - 时间戳打开的会话:14569591031   23:51:43.185 TRACE org.hibernate.internal.SessionImpl - 将刷新模式设置为:AUTO   23:51:43.186 TRACE org.hibernate.internal.SessionImpl - 将缓存模式设置为:NORMAL   23:51:43.189 DEBUG org.springframework.orm.jpa.EntityManagerFactoryUtils - 为JPA EntityManager注册事务同步   23:51:43.207 TRACE org.springframework.transaction.support.TransactionSynchronizationManager - 结合的值[org.springframework.orm.jpa.EntityManagerHolder@1028e769用于键[org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@3d018d7d]线程[HTTP -NiO-8443-EXEC-2]   23:51:43.208 TRACE org.hibernate.engine.query.spi.QueryPlanCache - 位于缓存中的HQL查询计划(更新用户u set u.loginVersuche = u.loginVersuche + 1,u.gesperrt =?1其中u.email = ?2)   23:51:43.210 TRACE org.springframework.transaction.support.TransactionSynchronizationManager - 检索到的值[org.springframework.orm.jpa.EntityManagerHolder@1028e769用于键[org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@3d018d7d]结合到线程[ HTTP-NIO-8443-EXEC-2]   23:51:43.214 DEBUG org.hibernate.jpa.spi.AbstractEntityManagerImpl - 标记回滚事务   23:51:43.215 TRACE org.springframework.transaction.interceptor.TransactionInterceptor - 异常后完成[org.springframework.data.jpa.repository.support.SimpleJpaRepository.incrementLoginVersuche]的事务:javax.persistence.TransactionRequiredException:执行更新/删除询问   23:51:43.217 TRACE org.springframework.transaction.interceptor.RuleBasedTransactionAttribute - 应用规则来确定事务是否应该在javax.persistence.TransactionRequiredException上回滚:执行更新/删除查询

UPDATE-3

TransactionManager配置:

@Bean(name = "transactionManager")
    public PlatformTransactionManager txManager() {
        return new DataSourceTransactionManager(dataSource());
    }

3 个答案:

答案 0 :(得分:1)

根据docs (4.6. Transactionality)

  

默认情况下,存储库实例上的CRUD方法是事务性的

因此您不需要在@Transactional(readOnly = true)界面上方添加UserDAO注释。 相反,您应该使您的保存方法具有事务性(假设您的类是有效的Spring组件):

@Transactional
public void incrementVersuche() {
    ...    
    User userByDB = userDAO.findByEmail(username);    
    userByDB.setLoginVersuche(userByDB.getLoginVersuche()+1);
    userDAO.save(userByDB);
}

<强>更新

public interface IUserSaver { 
        void incrementVersucheAndSave(String username)
}

@Service
public class UserSaver implements IUserSaver {

@Transactional
public void incrementVersucheAndSave(String username) {
        User userByDB = userDAO.findByEmail(username);    
        userByDB.setLoginVersuche(userByDB.getLoginVersuche()+1);
        userDAO.save(userByDB);
      }
}

然后在你的AuthProvider中:

....
@Autowired
private IUserSaver saver;

 public void incrementLoginVersuche() {
   ....
   saver.incrementVersucheAndSave(username);
}

答案 1 :(得分:0)

删除

  

@Transactional(readOnly = true)

来自您的存储库的

。该事务不会抛出异常: @Transactional readOnly

答案 2 :(得分:0)

没有事务调用的方法。检查你的tr demercations或来电环境。不是事务性的。原始问题:如果设置tr RO,它将不会执行更新SQL命令。