我收到此错误:
javax.persistence.TransactionRequiredException:执行更新/删除查询
我没有找到解决方法。似乎与我的代码中的@Transactional
批注有关:
@Service
@Transactional(rollbackFor = Exception.class, value = "transactionManager")
public class WxLoginServiceImpl implements WxService {
...但是我不知道该如何修改。
修改初始化创建后我遇到了这个问题,所以我认为这个问题是由于初始化之后的时间造成的。
完整错误是:
2018-12-27 23:35:59.959 ERROR 18525 --- [nio-8888-exec-2] o.a.c.c.C.[.[.[.[dispatcherServlet] :
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception
[Request processing failed;
nested exception is javax.persistence.TransactionRequiredException:
Executing an update/delete query] with root cause
javax.persistence.TransactionRequiredException: Executing an update/delete query
at org.hibernate.query.internal.AbstractProducedQuery.executeUpdate(AbstractProducedQuery.java:1586) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at com.querydsl.jpa.impl.JPAUpdateClause.execute(JPAUpdateClause.java:77) ~[querydsl-jpa-4.1.4.jar:?]
at com.genius.martial.service.impl.WxLoginServiceImpl.updateUserGroupByOpenId(WxLoginServiceImpl.java:87) ~[classes/:?]
at com.genius.martial.service.impl.WxLoginServiceImpl$$FastClassBySpringCGLIB$$7b7d6928.invoke(<generated>) ~[classes/:?]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:749) ~[spring-aop-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294) ~[spring-tx-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) ~[spring-tx-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) ~[spring-aop-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at com.genius.martial.service.impl.WxLoginServiceImpl$$EnhancerBySpringCGLIB$$63521827.updateUserGroupByOpenId(<generated>) ~[classes/:?]
at com.genius.martial.controller.WxController.updateUserGroupByOpenId(WxController.java:63) ~[classes/:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_131]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_131]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_131]
at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_131]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:189) ~[spring-web-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) ~[spring-web-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102) ~[spring-webmvc-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) ~[spring-webmvc-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:800) ~[spring-webmvc-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1038) ~[spring-webmvc-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942) ~[spring-webmvc-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005) ~[spring-webmvc-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:897) ~[spring-webmvc-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:634) ~[tomcat-embed-core-9.0.13.jar:9.0.13]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882) ~[spring-webmvc-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) ~[tomcat-embed-core-9.0.13.jar:9.0.13]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.13.jar:9.0.13]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.13.jar:9.0.13]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.13.jar:9.0.13]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.13.jar:9.0.13]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.13.jar:9.0.13]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.13.jar:9.0.13]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.13.jar:9.0.13]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92) ~[spring-web-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.13.jar:9.0.13]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.13.jar:9.0.13]
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93) ~[spring-web-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.13.jar:9.0.13]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.13.jar:9.0.13]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) ~[spring-web-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.13.jar:9.0.13]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.13.jar:9.0.13]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199) [tomcat-embed-core-9.0.13.jar:9.0.13]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-9.0.13.jar:9.0.13]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490) [tomcat-embed-core-9.0.13.jar:9.0.13]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) [tomcat-embed-core-9.0.13.jar:9.0.13]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.13.jar:9.0.13]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) [tomcat-embed-core-9.0.13.jar:9.0.13]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) [tomcat-embed-core-9.0.13.jar:9.0.13]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408) [tomcat-embed-core-9.0.13.jar:9.0.13]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-9.0.13.jar:9.0.13]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:791) [tomcat-embed-core-9.0.13.jar:9.0.13]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1417) [tomcat-embed-core-9.0.13.jar:9.0.13]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.13.jar:9.0.13]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:1.8.0_131]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:1.8.0_131]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.13.jar:9.0.13]
at java.lang.Thread.run(Thread.java:748) [?:1.8.0_131]
这是数据库Java代码:
package com.genius.martial.config;
import cn.hutool.core.util.StrUtil;
import com.alibaba.druid.pool.DruidDataSource;
import lombok.extern.log4j.Log4j2;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jndi.JndiObjectFactoryBean;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import javax.naming.NamingException;
import javax.persistence.EntityManager;
import javax.sql.DataSource;
import java.sql.Connection;
@Configuration
@Log4j2
public class DBDataSourceConfig {
@Value("${spring.datasource.jndi-name:}")
private String jndiUrl;
@Value("${spring.datasource.jdbc-url:aaa}")
private String dbUrl;
@Value("${spring.datasource.username:ick_rcb}")
private String username;
@Value("${spring.datasource.password}")
private String password;
@Value("${spring.datasource.driver-class-name:oracle.jdbc.driver.OracleDriver}")
private String driverClassName;
@Value("${spring.datasource.initialSize:1}")
private int initialSize;
@Value("${spring.datasource.minIdle:5}")
private int minIdle;
@Value("${spring.datasource.maxActive:30}")
private int maxActive;
@Value("${spring.datasource.maxWait:3000}")
private int maxWait;
@Value("${spring.datasource.validationQuery:select 'x' from dual}")
protected String validationQuery;
@Value("${spring.datasource.testOnBorrow:true}")
private boolean testOnBorrow;
@Value("${spring.datasource.testOnReturn:true}")
private boolean testOnReturn;
@Value("${spring.datasource.queryTimeout:0}")
private int queryTimeout;
@Bean(name = "dbDataSource")
@Primary
public DataSource dbDataSource() throws Exception {
return createDataSource();
}
@Primary
@Bean(name = "transactionManager")
public DataSourceTransactionManager dbTransactionManager() throws Exception {
return new DataSourceTransactionManager(dbDataSource());
}
@Bean(name = "JdbcTemplate")
public JdbcTemplate JdbcTemplate(
@Qualifier("dbDataSource") DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
@Primary
@Bean(name = "entityManagerFactory")
public LocalContainerEntityManagerFactoryBean
entityManagerFactory() throws Exception {
HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
jpaVendorAdapter.setGenerateDdl(true);
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(dbDataSource());
factoryBean.setJpaVendorAdapter(jpaVendorAdapter);
factoryBean.setPackagesToScan("com.genius.martial.entity.DO");
return factoryBean;
}
@Primary
@Bean(name = "entityManager")
public EntityManager entityManager() throws Exception {
return entityManagerFactory().getObject().createEntityManager();
}
@Bean(name = "transactionManager")
PlatformTransactionManager transactionManagerSecondary() throws Exception {
return new JpaTransactionManager(entityManagerFactory().getObject());
}
/**
* 创建数据源
*
* @return
* @throws NamingException
* @throws IllegalArgumentException
*/
protected DataSource createDataSource() throws IllegalArgumentException, NamingException {
DataSource dataSource ;
log.info("[datasource] 初始化数据库连接池...");
if (StrUtil.isBlank(jndiUrl)) {
log.info("[datasource] 使用连接配置属性");
Object[] params = {getDbUrl(), getUsername(), getPassword(), getDriverClassName(), initialSize, minIdle, maxActive, maxWait, testOnReturn, getValidationQuery(), testOnBorrow};
log.info("[datasource] url: {}, username: {}, password: {}, driver: {}, initialSize: {}, minIdle: {}, maxActive: {}, maxWait: {}, testOnReturn: {}" +
" validationQuery: {}, testOnBorrow: {}", params);
DruidDataSource datasource = new DruidDataSource();
datasource.setUrl(getDbUrl());
datasource.setUsername(getUsername());
datasource.setPassword(getPassword());
datasource.setDriverClassName(getDriverClassName());
datasource.setQueryTimeout(queryTimeout);
//configuration
datasource.setInitialSize(initialSize);
datasource.setMinIdle(minIdle);
datasource.setMaxActive(maxActive);
datasource.setMaxWait(maxWait);
datasource.setTestOnReturn(testOnReturn);
datasource.setValidationQuery(getValidationQuery());
datasource.setTestOnBorrow(testOnBorrow);
dataSource = datasource;
} else {
log.info("[datasource] 连接到jndi({})...", jndiUrl);
//连接jndi
JndiObjectFactoryBean bean = new JndiObjectFactoryBean();
bean.setJndiName(jndiUrl);
bean.setProxyInterface(DataSource.class);
bean.setLookupOnStartup(false);
bean.afterPropertiesSet();
dataSource = (DataSource) bean.getObject();
}
try(Connection connection = dataSource.getConnection()) {
} catch (Exception e) {enter code here
log.error("[datasource] 连接失败!", e);
}
return dataSource;
}
public String getDbUrl() {
return dbUrl;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public String getDriverClassName() {
return driverClassName;
}
public String getValidationQuery() {
return validationQuery;
}
}
这是我的服务代码:
package com.genius.martial.service.impl;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.genius.martial.dao.WxRepository;
import com.genius.martial.entity.DO.QWxUserInfoPOJO;
import com.genius.martial.entity.DO.WxUserInfoPOJO;
import com.genius.martial.exception.BusinessException;
import com.genius.martial.service.WxService;
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import javax.persistence.EntityManager;
import javax.annotation.PostConstruct;
import javax.persistence.Transient;
/**
* @description:
* @author: Jihaotian
* @create: 2018-12-09 21:07
**/
@Service
@Transactional(rollbackFor = Exception.class, value = "transactionManager")
public class WxLoginServiceImpl implements WxService {
@Autowired
private WxRepository wxRepository;
//实体管理
@Autowired
private EntityManager entityManager;
//查询工厂
private JPAQueryFactory queryFactory;
//初始化查询工厂
@PostConstruct
public void init()
{
queryFactory = new JPAQueryFactory(entityManager);
}
@Value("${wx.AppID}")
private String appId;
@Value("${wx.AppSecret}")
private String appSecret;
@Override
public JSONObject getWxUnique(String code) {
RestTemplate restTemplate = new RestTemplate();
String wxUserInfo = restTemplate.getForObject("https://api.weixin.qq.com/sns/jscode2session?appid=" + appId + "&secret=" + appSecret + "&js_code=" + code + "&grant_type=authorization_code", String.class);
JSONObject wxUserInfoJson = JSON.parseObject(wxUserInfo);
return wxUserInfoJson;
}
@Override
public void updateWxUserInfo(WxUserInfoPOJO userInfo) {
wxRepository.save(userInfo);
}
@Override
@Modifying
public void updateUserGroupByOpenId(String group, String openid) {
if (StrUtil.isEmpty(group)||StrUtil.isEmpty(openid)){
throw new BusinessException("数据不能为空,请刷新后重试");
}
if (ObjectUtil.isNull(wxRepository.findByOpenId(openid))){
throw new BusinessException("没有该用户,请重试!");
}
QWxUserInfoPOJO qWxUserInfoPOJO = QWxUserInfoPOJO.wxUserInfoPOJO;
queryFactory.update(qWxUserInfoPOJO).where(qWxUserInfoPOJO.openId.eq(openid))
.set(qWxUserInfoPOJO.groupName,group)
.execute();
}
}