执行更新/删除查询

嗨,我正在用 spring 和 mongodb 使用 hibernate JPA,我正在 Glassfish-4.0上运行我的应用程序。

我的服务类别是:

@Component
public class Test {
@PersistenceContext
EntityManager em;
EntityManagerFactory emf;


@Transactional
public String persist(Details details) {
details.getUsername();
details.getPassword();


Query query = em.createNativeQuery("db.details.find(username="+details.getUsername()+"&password="+details.getPassword());


em.getTransaction().begin();
em.persist(details);
em.getTransaction().commit();
em.flush();
em.clear();
em.close();
query.executeUpdate();
System.out.println("Sucessful!");
return "persist";
}
}

我的 spring-context.xml 是:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-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/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">


<context:component-scan base-package="com.javapapers.spring.mvc" />
<context:annotation-config />
<mvc:annotation-driven />
<tx:annotation-driven transaction-manager="txManager" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/" />
<property name="suffix" value=".jsp" />
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="ogmTest"/>
</bean>
<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager">
</bean>
</beans>

我在代码中应用了一些更改,但是没有效果。 有人能帮我解决这个问题吗。 先谢谢你。

296127 次浏览

You need not to worry about begin and end transaction. You have already apply @Transactional annotation, which internally open transaction when your method starts and ends when your method ends. So only required this is to persist your object in database.

 @Transactional(readOnly = false, isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})


public String persist(Details details){
details.getUsername();
details.getPassword();
Query query = em.createNativeQuery("db.details.find(username= "+details.getUsername()+"& password= "+details.getPassword());


em.persist(details);
System.out.println("Sucessful!");
return "persist";
}

EDIT : The problem seems to be with your configuration file. If you are using JPA then your configuration file should have below configuration

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
p:entityManagerFactory-ref="entityManagerFactory" />
<bean id="jpaAdapter"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
p:database="ORACLE" p:showSql="true" />
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
p:persistenceUnitName="YourProjectPU"
p:persistenceXmlLocation="classpath*:persistence.xml"
p:dataSource-ref="dataSource" p:jpaVendorAdapter-ref="jpaAdapter">
<property name="loadTimeWeaver">
<bean
class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
</property>
<property name="persistenceProvider" ref="interceptorPersistenceProvider" />


</bean>

I am not sure if this will help your situation (that is if it stills exists), however, after scouring the web for a similar issue.

I was creating a native query from a persistence EntityManager to perform an update.

Query query = entityManager.createNativeQuery(queryString);

I was receiving the following error:

caused by: javax.persistence.TransactionRequiredException: Executing an update/delete query

Many solutions suggest adding @Transactional to your method. Just doing this did not change the error.

Some solutions suggest asking the EntityManager for a EntityTransaction so that you can call begin and commit yourself. This throws another error:

caused by: java.lang.IllegalStateException: Not allowed to create transaction on shared EntityManager - use Spring transactions or EJB CMT instead

I then tried a method which most sites say is for use application managed entity managers and not container managed (which I believe Spring is) and that was joinTransaction().

Having @Transactional decorating the method and then calling joinTransaction() on EntityManager object just prior to calling query.executeUpdate() and my native query update worked.

I hope this helps someone else experiencing this issue.

as form the configuration xml it is clear that you are going to use spring based transaction. Please make sure that the import which you are using for @Transactional is "org.springframework.transaction.annotation.Transactional"

in your case it might be "javax.transaction.Transactional"

Nothing seemed to work for me until I realized that my method was declared as public final instead of just public. The error was being caused by the final keyword. Removing it made the error go away.

How about moving @Transactional from method to class level? Worked for me in similar case, though I'm not 100% certain why.

I have also faced same issue when I work with Hibernate and Spring Jpa Data Repository. I forgot to place @Transactional on spring data repository method.

Its working for me after annotating with @Transactional.

In my case, I had the wrong @Transactional imported.

The correct one is:

import org.springframework.transaction.annotation.Transactional;

and not

import javax.transaction.Transactional;

After integrating Spring 4 with Hibernate 5 in my project and experiencing this problem, I found that I could prevent the error from appearing by changing the way of getting the session from sessionFactory.openSession() to sessionFactory.getCurrentSession(). the proper way to work out this bug may be keep using the same session for the binding transaction.opensession will always create a new session which doesnt like the former one holding a transaction configed.using getCurrentSession and adding additional property <property name="current_session_context_class">org.springframework.orm.hibernate5.SpringSessionContext</property> works fine for me.

I Got the same error.

I just added the @Transactional annotation of javax.transaction.Transactional on the method.

Update:

I would recommend using Spring's @Transactional annotation from org.springframework.transaction.annotation.Transactional;

I faced the same exception "TransactionRequiredException Executing an update/delete query" but for me the reason was that I've created another bean in the spring applicationContext.xml file with the name "transactionManager" refering to "org.springframework.jms.connection.JmsTransactionManager" however there was another bean with the same name "transactionManager" refering to "org.springframework.orm.jpa.JpaTransactionManager". So the JPA bean is overriten by the JMS bean.

After renaming the bean name of the Jms, issue is resolved.

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;




@Transactional
public int changepassword(String password, long mobile) {
// TODO Auto-generated method stub
session = factory.getCurrentSession();
Query query = session.createQuery("update User u set u.password='" + password + "' where u.mobile=" + mobile);
int result = query.executeUpdate();


return result;
}
add this code 200% it will work... might scenario is diff but write like this:)

I received this exception when trying to run a bulk UPDATE query in a non-JTA (i.e. resource-local) entity manager in Java SE. I had simply forgotten to wrap my JPQL code in

em.getTransaction().begin();

and

em.getTransaction().commit();

Just add @Transactional on method level or class level. When you are updating or deleting record/s you have to maintain persistence state of Transaction and @Transactional manages this.

and import org.springframework.transaction.annotation.Transactional;

I was facing the same error inspite of adding @Transactional annotation at class level and importing org.springframework.transaction.annotation.Transactional.

Then I realized that since I was using hibernate query, I had imported javax.persistence.Query instead of import org.hibernate.query.Query. Therefore adding import org.hibernate.query.Query solved the issue for me.

I hope this idea helps someone.

Faced the same problem, I simply forgot to activate the transaction management with the @EnableTransactionManagement annotation.

Ref:

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/annotation/EnableTransactionManagement.html

Error message while running the code:

javax.persistence.TransactionRequiredException: Executing an update/delete query

Begin the entityManager transaction -> createNativeQuery -> execute update -> entityManager transaction commit to save it in your database. It is working fine for me with Hibernate and postgresql.

Code

entityManager.getTransaction().begin();
Query query = entityManager.createNativeQuery("UPDATE tunable_property SET tunable_property_value = :tunable_property_value WHERE tunable_property_name = :tunable_property_name");
query.setParameter("tunable_property_name", tunablePropertyEnum.eEnableJobManager.getName());
query.setParameter("tunable_property_value", tunable_property_value);
query.executeUpdate();
entityManager.getTransaction().commit();

Using @Modifying and @Transaction fixed me

  1. @Modifying @Query(value="DELETE FROM lock WHERE user_id = ?1" ,nativeQuery=true) void deleteByUserId(Long userId);

  2. @Service @Transactional

Using @PersistenceContext with @Modifying as below fixes error while using createNativeQuery

    import org.springframework.data.jpa.repository.Modifying;
import org.springframework.transaction.annotation.Transactional;


import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;


@PersistenceContext
private EntityManager entityManager;


@Override
@Transactional
@Modifying
public <S extends T> S save(S entity) {
Query q = entityManager.createNativeQuery(...);
q.setParameter...
q.executeUpdate();
return entity;
}

I was also getting this issue in springboot project and added @Transactional in my class and it is working.

import org.springframework.transaction.annotation.Transactional;
@Transactional
public class SearchRepo {
---
}

If the previous answers fail, make sure you use @Service stereotype for the class where you call the update method on your repository. I originally used @Component instead and it was not working, the simple change to @Service made it work.

The same exception occurred to me in a somewhat different situation. Since I've been searching here for an answer, maybe it'll help somebody.

I my case the exception has been happening because I called the (properly annotated) @Transactional method from a SERVICE CONSTRUCTOR... Since my idea was simply to make this method run at the start, I annotated it as following, and stopped calling in a wrong way. Exception is gone, and code is better :)

@EventListener(ContextRefreshedEvent.class)
@Transactional
public void methodName() {...}

@Transactional import: import org.springframework.transaction.annotation.Transactional;

Following advice from Baeldung JPA Transaction Required Exception

Basically wrap your commit code in

Transaction transaction = session.beginTransaction();
....update or save or delete here
transaction.commit();

I faced the same exception and Loop through save entity like:

relationships.stream().parallel().forEach

modify as:

  relationships.forEach

now it was working。

incase if you have more than one datasource and more than transaction manager, or you have customized your PlatformTransactionManager like I did in this example , then: you have to put your transaction manager name in the

@Transactional("wptransactionManager")

here was my DB1 Datasource1 class ( have 2 transaction managers and 2 datasources etc ..


@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "wpentityManagerFactory", basePackages = {
"xxx.xxx.xxx.wp.repository" })
public class WpDBConfigAhmedYousri {


@Bean(name = "wpdataSource")
@ConfigurationProperties(prefix = "spring.user.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}




@Bean(name = "wpentityManagerFactory")
public LocalContainerEntityManagerFactoryBean wpentityManagerFactory(EntityManagerFactoryBuilder builder,
@Qualifier("wpdataSource") DataSource dataSource) {
HashMap<String, Object> properties = new HashMap<>();
properties.put("hibernate.hbm2ddl.auto", "none");
properties.put("hibernate.dialect", "org.hibernate.dialect.MySQL5InnoDBDialect");
return builder.dataSource(dataSource).properties(properties)
.packages("xxx.xxx.xxx.wp.models").persistenceUnit("User").build();
}


-----> @Bean(name = "wptransactionManager")
public PlatformTransactionManager transactionManager(
@Qualifier("wpentityManagerFactory") EntityManagerFactory wpentityManagerFactory) {
return new JpaTransactionManager(wpentityManagerFactory);
}
}

My Repository:


@Repository
public interface WpCommenntsRepository extends JpaRepository<WpComments, Long> {






@Modifying
@Query(value = "insert into WpComments (comment_author) VALUES (:comment_author)", nativeQuery = true)
----->   @Transactional("wptransactionManager")
public int insertNewComment(@Param("comment_author")String comment_author);


}


my example of update query thas working after adding @Transactional

    @Modifying
@Query("UPDATE UserInfo AS u SET u.failedAttempt = :failedAttempt WHERE u.email =:email")
@Transactional
@Modifying
public void updateFailedAttempts(@Param("failedAttempt") int failedAttempts, @Param("email") String email);

I had the same error, just annotated with @Transactional and it worked