Query.unwrap 报错com.sun.proxy.$Proxy cannot be cast to org.hibernate.query

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;
    }
}

 

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值