1.由于hibernate 5.2 之后,SQLQuery.class、setResultTransformer方法已作废,
更新前其用法如下:
Query query = entityManager.createNativeQuery(sql, clazz);
query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
替换后为:Query query = entityManager.createNativeQuery(sql, clazz);
query.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
2.更新后很奇怪的报了异常:
java.lang.ClassCastException: com.sun.proxy.$Proxy330 cannot be cast to org.hibernate.query.internal.NativeQueryImpl at com.tyyw.lcba.ajfw.infrastructure.util.DynamicSqlUtil.queryData(DynamicSqlUtil.java:97) at com.tyyw.lcba.ajfw.infrastructure.util.DynamicSqlUtil
从以上可以产出是jdk的代理在搞鬼。打了一波断点,发现在方法运行到该行的时候确实是jdk代理对象,然后强转报错。
3.解决
有两个思路:
①更换springboot的代理模式为CGLIB(经尝试无效)
②直接获取到正确的对象不强转(很麻烦,代码可扩容性不强)
经尝试,添加一个声明式事务管理切面,springboot2.X 版本会自动使用cglib代理,如此便优雅的解决了这个问题,代码如下:
import org.aspectj.lang.annotation.Aspect; import org.springframework.aop.Advisor; import org.springframework.aop.aspectj.AspectJExpressionPointcut; import org.springframework.aop.support.DefaultPointcutAdvisor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.interceptor.*; import javax.sql.DataSource; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Properties; /** * @description: 事务管理切面 * @author: lc * @create: 2019-10-24 15:24 **/ @Aspect @Configuration public class TransactionManagerConfiguration { @Autowired private DataSource dataSource; /** * 切点(只切有service注解的) */ private static final String AOP_POINTCUT_EXPRESSION = "(@within(org.springframework.stereotype.Service))"; /** * 默认的需要事务的操作 */ private static final String[] DEFAULT_TRANSACTION_ATTRIBUTES = {"add*", "save*", "insert*", "delete*", "update*", "edit*", "batch*", "create*", "remove*"}; /** * 只读操作 */ private static final String[] DEFAULT_READ_ONLY_TRANSACTION_ATTRIBUTES = {"get*", "count*", "find*", "query*", "select*", "list*", "page*","*",}; @Bean public TransactionInterceptor txAdvice(@Autowired PlatformTransactionManager transactionManager) { NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource(); RuleBasedTransactionAttribute readOnlyTx = this.readOnlyBasedTransactionAttribute(); RuleBasedTransactionAttribute requiredTx = this.transactionRuleBasedTransactionAttribute(); Map<String, TransactionAttribute> txMap = new HashMap<>(); for (String readOnly : DEFAULT_READ_ONLY_TRANSACTION_ATTRIBUTES) { txMap.put(readOnly, readOnlyTx); } for (String transaction : DEFAULT_TRANSACTION_ATTRIBUTES) { txMap.put(transaction, requiredTx); } source.setNameMap(txMap); TransactionInterceptor transactionInterceptor = new TransactionInterceptor(transactionManager,source); transactionInterceptor.setTransactionManager(transactionManager); Properties transactionAttributes = new Properties(); transactionAttributes.setProperty("*", "PROPAGATION_REQUIRED,-Throwable"); transactionInterceptor.setTransactionAttributes(transactionAttributes); return transactionInterceptor; } @Bean public Advisor txAdviceAdvisor(TransactionInterceptor txAdvice) { AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut(); pointcut.setExpression(AOP_POINTCUT_EXPRESSION); return new DefaultPointcutAdvisor(pointcut, txAdvice); } /** * @Description: 获取只读操作 * @Param: * @return: * @Author: lc * @Date: 2019/10/24 0024 16:19 */ private RuleBasedTransactionAttribute readOnlyBasedTransactionAttribute(){ /*只读事务,不做更新操作*/ RuleBasedTransactionAttribute readOnlyTx = new RuleBasedTransactionAttribute(); readOnlyTx.setReadOnly(true); readOnlyTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED); return readOnlyTx; } /** * @Description: 获取事务操作 * @Param: * @return: * @Author: lc * @Date: 2019/10/24 0024 16:19 */ private RuleBasedTransactionAttribute transactionRuleBasedTransactionAttribute (){ RuleBasedTransactionAttribute requiredTx = new RuleBasedTransactionAttribute(); requiredTx.setRollbackRules(Collections.singletonList(new RollbackRuleAttribute(Exception.class))); requiredTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); return requiredTx; } }