无法删除行:TransactionRequiredException:正在执行 update/delete 查询
Unable to delete row : TransactionRequiredException: Executing an update/delete query
关于这个问题有好几篇帖子,但仍然没有得到解决方案。
这是 parent class 用户。
在 @OneToMany 关系中,我想删除一个特定的 child 帐户。
现在,当我通过 "DELETE" 查询执行此操作时,出现以下异常。
org.springframework.dao.InvalidDataAccessApiUsageException: 执行一个update/delete查询;嵌套异常是 javax.persistence.TransactionRequiredException:执行 update/delete 查询
@RooJavaBean
@RooToString
@RooJpaEntity
@RooJpaActiveRecord(finders = { "findUserrsByUserName"})
public class Userr {
@NotNull
@Column(unique = true)
private String userName;
@NotNull
private int userType;
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
private List<Account> accounts = new ArrayList<Account>();
}
Child class
@RooJavaBean
@RooToString
@RooJpaActiveRecord
@RooJpaEntity
public class Account {
@OneToMany(mappedBy="account", fetch=FetchType.LAZY, cascade = CascadeType.ALL)
List<Message> messages = new ArrayList<Message>();
/*@OneToMany(mappedBy="account", fetch=FetchType.LAZY, cascade = CascadeType.ALL)
List<PremiumPlayPositionCombination> premiumPlayPosition = new ArrayList<PremiumPlayPositionCombination>();*/
@OneToMany(mappedBy="account", fetch=FetchType.LAZY, cascade = CascadeType.ALL)
List<PositionCombinationArc> allPositionsArc = new ArrayList<PositionCombinationArc>();
@ManyToOne
@JoinColumn(name="user_id")
private Userr user;
}
这是我的删除查询
@Transactional
public static void deleteClientByClientId(Long clientId) {
System.out.println("Delete query findUsersClientsByUser" + clientId);
int deleteCount= entityManager().createQuery("DELETE FROM Account where id =:clientId").setParameter("clientId", clientId).executeUpdate();
System.out.println("Delete query findUsersClientsByUser" + deleteCount);
}
我在 ApplicationContext-security.xml 中添加了这样
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!--
This will automatically locate any and all property files you have
within your classpath, provided they fall under the META-INF/spring
directory. The located property files are parsed and their values can
then be used within application context files in the form of
${propertyKey}.
-->
<context:property-placeholder location="classpath*:META-INF/spring/*.properties"/>
<!--
Turn on AspectJ @Configurable support. As a result, any time you
instantiate an object, Spring will attempt to perform dependency
injection on that object. This occurs for instantiation via the "new"
keyword, as well as via reflection. This is possible because AspectJ
is used to "weave" Roo-based applications at compile time. In effect
this feature allows dependency injection of any object at all in your
system, which is a very useful feature (without @Configurable you'd
only be able to dependency inject objects acquired from Spring or
subsequently presented to a specific Spring dependency injection
method). Roo applications use this useful feature in a number of
areas, such as @PersistenceContext injection into entities.
-->
<context:spring-configured/>
<bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource">
<property name="driverClassName" value="${database.driverClassName}"/>
<property name="url" value="${database.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
</bean>
<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="smtp.gmail.com"/>
<property name="port" value="587"/>
<property name="username" value="noreply@uforic.in"/>
<property name="password" value="noreply@123"/>
<property name="javaMailProperties">
<props>
<prop key="mail.transport.protocol">smtp</prop>
<prop key="mail.smtp.auth">true</prop>
<prop key="mail.smtp.starttls.enable">true</prop>
<prop key="mail.debug">true</prop>
</props>
</property>
</bean>
<!--
This declaration will cause Spring to locate every @Component,
@Repository and @Service in your application. In practical terms this
allows you to write a POJO and then simply annotate the new POJO as an
@Service and Spring will automatically detect, instantiate and
dependency inject your service at startup time. Importantly, you can
then also have your new service injected into any other class that
requires it simply by declaring a field for your service inside the
relying class and Spring will inject it. Note that two exclude filters
are declared. The first ensures that Spring doesn't spend time
introspecting Roo-specific ITD aspects. The second ensures Roo doesn't
instantiate your @Controller classes, as these should be instantiated
by a web tier application context. Refer to web.xml for more details
about the web tier application context setup services.
Furthermore, this turns on @Autowired, @PostConstruct etc support. These
annotations allow you to use common Spring and Java Enterprise Edition
annotations in your classes without needing to do any special configuration.
The most commonly used annotation is @Autowired, which instructs Spring to
dependency inject an object into your class.
-->
<context:component-scan base-package="com.uforic.optionstrader">
<context:exclude-filter expression=".*_Roo_.*" type="regex"/>
<!--context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/-->
</context:component-scan>
在 Spring 上下文文件中,您需要添加以下代码:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<tx:annotation-driven />
此外,添加您的 spring security
bean 配置。
您可以在代码中检查以下内容:
如果您使用的是基于 spring 的事务,请确保为 @Transactional 注释导入 org.springframework.transaction.annotation.Transactional class
在您的情况下,它可能是 javax.transaction.Transactional
我在您的代码中看到 deleteClientByClientId 方法是静态的。 spring 中的@Transactional 不支持静态方法。使您的方法成为非静态的,并被注释为事务性的。
可以参考@Transactional with static method
让我知道哪个选项适合您。
当尝试 update/delete 使用 Hibernate 时,必须用事务 Begin() 和 Commit() 示例包围查询:
EntityTransaction tr=em.getTransaction();
tr.begin();
Query query = (Query) em.createQuery( "update etudiant set email= :em, adresse= :adr,telephone= :tele,password= :pwd"
+ " where email= :mail");
query.setParameter("em", email)
.setParameter("adr", adresse)
.setParameter("tele", tele)
.setParameter("pwd", pass)
.setParameter("mail", ancienEmail);
int a= query.executeUpdate();
tr.commit();
关于这个问题有好几篇帖子,但仍然没有得到解决方案。 这是 parent class 用户。 在 @OneToMany 关系中,我想删除一个特定的 child 帐户。
现在,当我通过 "DELETE" 查询执行此操作时,出现以下异常。
org.springframework.dao.InvalidDataAccessApiUsageException: 执行一个update/delete查询;嵌套异常是 javax.persistence.TransactionRequiredException:执行 update/delete 查询
@RooJavaBean
@RooToString
@RooJpaEntity
@RooJpaActiveRecord(finders = { "findUserrsByUserName"})
public class Userr {
@NotNull
@Column(unique = true)
private String userName;
@NotNull
private int userType;
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
private List<Account> accounts = new ArrayList<Account>();
}
Child class
@RooJavaBean
@RooToString
@RooJpaActiveRecord
@RooJpaEntity
public class Account {
@OneToMany(mappedBy="account", fetch=FetchType.LAZY, cascade = CascadeType.ALL)
List<Message> messages = new ArrayList<Message>();
/*@OneToMany(mappedBy="account", fetch=FetchType.LAZY, cascade = CascadeType.ALL)
List<PremiumPlayPositionCombination> premiumPlayPosition = new ArrayList<PremiumPlayPositionCombination>();*/
@OneToMany(mappedBy="account", fetch=FetchType.LAZY, cascade = CascadeType.ALL)
List<PositionCombinationArc> allPositionsArc = new ArrayList<PositionCombinationArc>();
@ManyToOne
@JoinColumn(name="user_id")
private Userr user;
}
这是我的删除查询
@Transactional
public static void deleteClientByClientId(Long clientId) {
System.out.println("Delete query findUsersClientsByUser" + clientId);
int deleteCount= entityManager().createQuery("DELETE FROM Account where id =:clientId").setParameter("clientId", clientId).executeUpdate();
System.out.println("Delete query findUsersClientsByUser" + deleteCount);
}
我在 ApplicationContext-security.xml 中添加了这样
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!--
This will automatically locate any and all property files you have
within your classpath, provided they fall under the META-INF/spring
directory. The located property files are parsed and their values can
then be used within application context files in the form of
${propertyKey}.
-->
<context:property-placeholder location="classpath*:META-INF/spring/*.properties"/>
<!--
Turn on AspectJ @Configurable support. As a result, any time you
instantiate an object, Spring will attempt to perform dependency
injection on that object. This occurs for instantiation via the "new"
keyword, as well as via reflection. This is possible because AspectJ
is used to "weave" Roo-based applications at compile time. In effect
this feature allows dependency injection of any object at all in your
system, which is a very useful feature (without @Configurable you'd
only be able to dependency inject objects acquired from Spring or
subsequently presented to a specific Spring dependency injection
method). Roo applications use this useful feature in a number of
areas, such as @PersistenceContext injection into entities.
-->
<context:spring-configured/>
<bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource">
<property name="driverClassName" value="${database.driverClassName}"/>
<property name="url" value="${database.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
</bean>
<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="smtp.gmail.com"/>
<property name="port" value="587"/>
<property name="username" value="noreply@uforic.in"/>
<property name="password" value="noreply@123"/>
<property name="javaMailProperties">
<props>
<prop key="mail.transport.protocol">smtp</prop>
<prop key="mail.smtp.auth">true</prop>
<prop key="mail.smtp.starttls.enable">true</prop>
<prop key="mail.debug">true</prop>
</props>
</property>
</bean>
<!--
This declaration will cause Spring to locate every @Component,
@Repository and @Service in your application. In practical terms this
allows you to write a POJO and then simply annotate the new POJO as an
@Service and Spring will automatically detect, instantiate and
dependency inject your service at startup time. Importantly, you can
then also have your new service injected into any other class that
requires it simply by declaring a field for your service inside the
relying class and Spring will inject it. Note that two exclude filters
are declared. The first ensures that Spring doesn't spend time
introspecting Roo-specific ITD aspects. The second ensures Roo doesn't
instantiate your @Controller classes, as these should be instantiated
by a web tier application context. Refer to web.xml for more details
about the web tier application context setup services.
Furthermore, this turns on @Autowired, @PostConstruct etc support. These
annotations allow you to use common Spring and Java Enterprise Edition
annotations in your classes without needing to do any special configuration.
The most commonly used annotation is @Autowired, which instructs Spring to
dependency inject an object into your class.
-->
<context:component-scan base-package="com.uforic.optionstrader">
<context:exclude-filter expression=".*_Roo_.*" type="regex"/>
<!--context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/-->
</context:component-scan>
在 Spring 上下文文件中,您需要添加以下代码:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<tx:annotation-driven />
此外,添加您的 spring security
bean 配置。
您可以在代码中检查以下内容:
如果您使用的是基于 spring 的事务,请确保为 @Transactional 注释导入 org.springframework.transaction.annotation.Transactional class 在您的情况下,它可能是 javax.transaction.Transactional
我在您的代码中看到 deleteClientByClientId 方法是静态的。 spring 中的@Transactional 不支持静态方法。使您的方法成为非静态的,并被注释为事务性的。 可以参考@Transactional with static method
让我知道哪个选项适合您。
当尝试 update/delete 使用 Hibernate 时,必须用事务 Begin() 和 Commit() 示例包围查询:
EntityTransaction tr=em.getTransaction();
tr.begin();
Query query = (Query) em.createQuery( "update etudiant set email= :em, adresse= :adr,telephone= :tele,password= :pwd"
+ " where email= :mail");
query.setParameter("em", email)
.setParameter("adr", adresse)
.setParameter("tele", tele)
.setParameter("pwd", pass)
.setParameter("mail", ancienEmail);
int a= query.executeUpdate();
tr.commit();