sqlSessionFactory提示需要注入-mybatis版本升级问题排查过程

3552 篇文章 114 订阅

问题背景

我们在写业务需求的时候遇到这样一个场景:批量插⼊⼀批数据到⼀张表中,然后获取到插⼊的Id,并将这些Id返回。

⾸先mybatis是⽀持单个数据插⼊返回Id的,实际上,mybatis也⽀持批量插⼊返回Id

<!-- 批量新增 --> 
 <insert id="batchInsert" parameterType="java.util.List"
    useGeneratedKeys="true" keyProperty="id" >
    INSERT INTO 
 <include refid="t_shop_resource" />
            (relation_id, summary_id, relation_type)
    VALUES
            <foreach collection="list" index="index" item="shopResource"
    separator=",">
            (
            #{shopResource.relationId}, #{shopResource.summaryId}, #
    {shopResource.relationType} 
 ) 
 </foreach> 
 </insert>
复制代码

如果要使用批量插入返回id,需要升级Mybatis版本到3.3.1。因为官⽅在这个版本中加⼊了批量新增返回主键id的功能。

但是升级mybatis版本需要升级对应的mybatis-spring版本。否则会出现版本兼容问题。修改pom⽂件

<mybatis.version>3.4.0</mybatis.version> 
<mybatis-spring.version>1.3.0</mybatis-spring.version>
复制代码

结果发现启动的时候报错,提示:

Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required
复制代码

问题原因

排查思路

  • 根据错误⽇志Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required的提示 定位到SqlSessionDaoSupport类。

  • 我们使⽤的项⽬是基于GenericDAO的⽼项⽬,所有的Dao实现类都继承GenericDAOImpl,⽽GenericDAOImpl⼜继承SqlSessionDaoSupport类。

  • SqlSessionDaoSupport类的实现如下所示:

public abstract class SqlSessionDaoSupport extends DaoSupport {
    private SqlSession sqlSession;
    private boolean externalSqlSession;
    public SqlSessionDaoSupport() {
    }
    public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
        if (!this.externalSqlSession) {
            this.sqlSession = new SqlSessionTemplate(sqlSessionFactory);
        }
    }
    public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
        this.sqlSession = sqlSessionTemplate;
        this.externalSqlSession = true;
    }
    public SqlSession getSqlSession() {
        return this.sqlSession;
    }
    protected void checkDaoConfig() {
        Assert.notNull(this.sqlSession, "Property 'sqlSessionFactory' or
        'sqlSessionTemplate' are required");
    }
}
复制代码
  • 可以看到报错是在checkDaoConfig⾥报的。SqlSessionDaoSupport继承了DaoSupport,DaoSupport继承了InitializingBean,在初始化之后,会去调⽤checkDaoConfig⽅法,结果由于我们没有注⼊SqlSessionFactory,因此就没有校验通过。
public abstract class DaoSupport implements InitializingBean {
    protected final Log logger = LogFactory.getLog(this.getClass());
    public DaoSupport() {
    }
    public final void afterPropertiesSet() throws IllegalArgumentException,
            BeanInitializationException {
        this.checkDaoConfig();
        try {
            this.initDao();
        } catch (Exception var2) {
            throw new BeanInitializationException("Initialization of DAO
                    failed", var2);
        }
    }
    protected abstract void checkDaoConfig() throws IllegalArgumentException;
    protected void initDao() throws Exception {
    }
}
复制代码

那么为什么⽼版本没有问题呢,再次将版本回退,再次进⼊该类观察:

public abstract class SqlSessionDaoSupport extends DaoSupport {
    private SqlSession sqlSession;
    private boolean externalSqlSession;
    public SqlSessionDaoSupport() {
    }
    @Autowired(
            required = false
    )
    public final void setSqlSessionFactory(SqlSessionFactory
                                                   sqlSessionFactory) {
        if (!this.externalSqlSession) {
            this.sqlSession = new SqlSessionTemplate(sqlSessionFactory);
        }
    }
    @Autowired(
            required = false
    )
    public final void setSqlSessionTemplate(SqlSessionTemplate
                                                    sqlSessionTemplate) {
        this.sqlSession = sqlSessionTemplate;
        this.externalSqlSession = true;
    }
    public final SqlSession getSqlSession() {
        return this.sqlSession;
    }
    protected void checkDaoConfig() {
        Assert.notNull(this.sqlSession, "Property 'sqlSessionFactory' or
        'sqlSessionTemplate' are required");
    }
}
复制代码
  • 可以看到在⽼版本中,是会⾃动注⼊sqlSessionFactory和sqlSessionTemplate的,⽽新版本取消了这⼀做法,需要我们⼿动注⼊。(mybatis-spring 1.2.0后取消)。

解决方法

1、新写⼀个公共⼦类,然后所有的Dao继承这个公共⼦类,公共⼦类继承GenericDAOImpl,⼿动注⼊SqlSessionFactory

public class CommonDao extends GenericDAOImpl {
    @Resource
    public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory){
        super.setSqlSessionFactory(sqlSessionFactory);
    }
}
复制代码

所有的dao实现类继承CommonDao。

@Repository
class UserDaoImpl implements UserDao extends CommonDao {
}
复制代码

2、但是基于CommonDao的思路,改动量过多,影响范围不可控制,因此最终选择不升级mybatis版本。批量插⼊返回Id,采⽤先插⼊再根据唯⼀主键查询的⽅式。 由于Dao继承GenericDao的⽅式代码冗余过多且不够灵活,因此新项⽬⼀般使⽤mybatis-plus。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值