Java 使用Spring Repo更新OneTONE列
我的Spring Boot应用程序中有两个实体: 用户:Java 使用Spring Repo更新OneTONE列,java,spring,spring-mvc,spring-data,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 =
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...
}
我有我的刀:
@Repository
public interface UserDAO extends CrudRepository<User, Integer>{
User findByEmail(String user);
}
它只是不更新数据库中的数据字段,但我也没有得到任何错误。这与我在用户中的主键(外键)有关吗?
更新-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);
更新-2
23:51:43.181跟踪org.springframework.transaction.support.TransactionSynchronizationManager-初始化事务同步
23:51:43.182跟踪org.springframework.transaction.interceptor.TransactionInterceptor-获取[org.springframework.data.jpa.repository.support.SimpleParepository.incrementLoginVersuche]的事务
23:51:43.183调试org.springframework.orm.jpa.EntityManager工厂utils-打开jpa EntityManager
23:51:43.184跟踪org.hibernate.internal.SessionFactoryImpl$SessionBuilderImpl-打开hibernate会话。租户=null,所有者=org.hibernate.jpa.internal。EntityManagerImpl@71dfe394
23:51:43.184 TRACE org.hibernate.internal.SessionImpl-时间戳为14569591031的已打开会话
23:51:43.185跟踪org.hibernate.internal.SessionImpl-将刷新模式设置为:自动
23:51:43.186跟踪org.hibernate.internal.SessionImpl-将缓存模式设置为:正常
23:51:43.189调试org.springframework.orm.jpa.EntityManagerFactoryUtils-为jpa EntityManager注册事务同步
23:51:43.207跟踪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跟踪org.hibernate.engine.query.spi.QueryPlanCache-在缓存中找到HQL查询计划(更新用户u set u.loginVersuche=u.loginVersuche+1,u.gesperrt=?1,其中u.email=?2)
23:51:43.210跟踪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调试org.hibernate.jpa.spi.AbstractEntityManagerImpl-标记回滚事务
23:51:43.215 TRACE org.springframework.transaction.interceptor-在异常之后完成[org.springframework.data.jpa.repository.support.simplejpeparepository.incrementLoginVersuche]的事务:javax.persistence.TransactionRequiredException:执行更新/删除查询
23:51:43.217跟踪org.springframework.transaction.interceptor.RuleBasedTransactionAttribute-应用规则确定事务是否应在javax.persistence.TransactionRequiredException上回滚异常:执行更新/删除查询
更新-3
TransactionManager配置:
@Bean(name = "transactionManager")
public PlatformTransactionManager txManager() {
return new DataSourceTransactionManager(dataSource());
}
据
默认情况下,存储库实例上的CRUD方法是事务性的
因此,在UserDAO
界面上方不需要@Transactional(readOnly=true)
注释。
相反,您应该使保存方法具有事务性(假设您的类是有效的Spring组件):
更新
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);
}
除去
@事务(只读=真)
从您的存储库中。事务将不会引发异常:
在没有事务的情况下调用的方法。检查您的tr描述或来电者环境。不是事务性的。最初的问题是:如果设置tr RO,它将不会执行更新SQL命令。好的,我实现了自己的查询(请参见更新的答案),但这也不起作用。所有注释都来自spring包。获取错误:
原因:javax.persistence.TransactionRequiredException:执行更新/删除查询
,但更重要的是:为什么我的第一次尝试不起作用?希望了解这一点。@Andy请在调用incrementLoginVersuche
方法的地方共享您的配置和服务。在配置中,您应该有类似于
的内容。有吗?还要注意,您的存储库不需要@Repository注释,因为它扩展了crudepository
。最后,由于您没有使用本机查询,我认为您应该像@query(“更新用户u set u.loginVersuche=u.loginVersuche+1,u.gesperrt=:gesperrt,其中u.email=:email”)
请参阅update-3,我使用的是Java配置而不是名称空间。除此之外,我还更新了我的查询,正如您所说:@query(“更新用户u set u.loginVersuche=u.loginVersuche+1,u.gesperrt=:gesperrt其中u.email=:email”)public int incrementLoginVersuche(@Param(“gesperrt”)boolean gesperrt,@Param(“email”)String email)
可以查看@TheBitman。您的配置上是否有@EnableTransactionManagement
注释?另外,(只是为了再次确认)检查您的所有注释是否都来自spring。是的,我在AppConfig中检查过,所有注释都来自spring。好的,请看一下我对@Enigo的评论。我现在调用“incrementLoginVersuche”(参见UPDATE-1),但现在得到的是由javax.persistence.TransactionRequiredException引起的:执行更新/删除查询
@Transactional设置如您所见。我正在通过我的身份验证提供者的身份验证-方法调用该方法。这并不能改变事实:您在没有tr的情况下调用了该方法。Maybee堆栈跟踪可能是一个错误的起点我是否理解错了什么?我的customAuthenticationProvider有一个覆盖方法:@Override public Authentication Authentication(Authentication Authentication)抛出AuthenticationException{…}
在这个函数中,我调用标记为事务的incrementLoginVersuche
。因此,它应该开始一项新的交易
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);
}
}
....
@Autowired
private IUserSaver saver;
public void incrementLoginVersuche() {
....
saver.incrementVersucheAndSave(username);
}