使用IDEA操作Maven项目+Mybatis框架的简单方法(1)

(此篇只记录连接数据库部分内容)

菜鸟心得小记,大神请无视

首先创建Maven项目(创建过程在此不作赘述)

在pom.xml配置文件中引入相关资源依赖

    <!--添加依赖-->
    <dependencies>
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.4</version>
        </dependency>
        <!--junit模块,方便测试代码-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <!--用来连接mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.41</version>
        </dependency>
        <!--记录运行日志,方便查找错误,同时会看到一些有意思的运行过程-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
    </dependencies>

在src/main/resources目录下创建三个配置文件


log4j配置百度上到处都是,在此不作赘述

database.properties文件配置如下图所示


myconfig.xml配置如下

<?xml version="1.0" encoding="UTF-8"?>
<!--表头可直接使用-->
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!--配置标签,添加database.properties进来,方便连接数据库-->
    <properties resource="database.properties"></properties>
    <!--设置日志实现方式为LOG4J-->
    <settings>
        <setting name="logImpl" value="LOG4J"/>
    </settings>
    <!--环境配置,default为设置默认调用的环境配置-->
    <environments default="dev">
        <environment id="dev">
            <!--事务管理方式为JDBC-->
            <transactionManager type="JDBC"></transactionManager>
            <!--数据源从连接池获取-->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"></property>
                <property name="url" value="${jdbc.url}"></property>
                <property name="username" value="${jdbc.username}"></property>
                <property name="password" value="${jdbc.password}"></property>
            </dataSource>
        </environment>
    </environments>
</configuration>

然后在src/main/java中创建MybatisUtil工具类

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;

public class MybatisUtil {
    //创建私有静态的引用,确保该引用只会建立一个且不能被外部直接修改
    private static SqlSessionFactory sqlSessionFactory=null;
    //使用静态代码块,以保证该部分代码在类加载的同时就能首先被加载
    static {
        try {
            //以输入流的形式读取配置文件
            InputStream inputStream= Resources.getResourceAsStream("mybatis-config.xml");
            //将工厂类的引用指向由SqlSessionBuilder类对象调用build(配置输入流)方法创建的SqlSession工厂类对象
            sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //获取SqlSession对象
    public static SqlSession createSqlSession(){
        return sqlSessionFactory.openSession();
    }
    //关闭sqlSession
    public static void closeSqlSession(SqlSession sqlSession){
        if(sqlSession!=null){
            sqlSession.close();
        }
    }
}

此时我们可以在src/test/java目录下创建测试类测试连接

import com.bdqn.util.MybatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

public class UserTest {
    @Test
    public void getConnTest(){
        //调用MybatisUtil类的类方法创建sqlSession对象
        
      SqlSession sqlSession=MybatisUtil.createSqlSession();
      if(sqlSession!=null){
      System.out.println("success");}
      MybatisUtil.closeSqlSession(sqlSession); }}

如果此前的一切配置无误,则会在控台输出“success”

刚刚接触以上代码的时候我就有个疑问,回想IO流的相关内容,我们在MybatisUtil工具类创建了一个字节流,可是放眼通篇代码都没有将它关闭,这显然是不合理的,所以一定是在其后的某个环节调用某个方法时自动关闭了该流,可疑性最大的自然是sqlSession.close(),顾名思义,这个方法最像是在做一些关闭流的工作,接下来就是查看深层代码的过程了。

通过万能的ctrl+左键我们进入到了DefaultSqlSession类,看到了如下代码

public void close() {
    try {
      executor.close(isCommitOrRollbackRequired(false));
      dirty = false;
    } finally {
      ErrorContext.instance().reset();
    }}

继续深入executor.close()方法,来到了BaseExecutor类,看到如下代码

public void close(boolean forceRollback) {
    try {
      try {
        rollback(forceRollback);
      } finally {
        if (transaction != null) transaction.close();
      }
    } catch (SQLException e) {
      // Ignore.  There's nothing that can be done at this point.
      log.debug("Unexpected exception on closing transaction.  Cause: " + e);
    } finally {
      transaction = null;
      deferredLoads = null;
      localCache = null;
      localOutputParameterCache = null;
      closed = true;
    }
  }

在这里我们看到了一个很熟悉的单词,transaction事务,继续深入close()方法,来到JdbcTransaction

public void close() throws SQLException {
    if (connection != null) {
      resetAutoCommit();
      if (log.isDebugEnabled()) {
        log.debug("Closing JDBC Connection [" + connection + "]");
      }
      connection.close();
    }
  }

此处的代码已经能看得很清楚了,重置了AutoCommit(Mysql事务自动提交属性),输出了关闭JDBC连接的相关日志信息,以及关闭了数据库连接,那么问题来了,IO流呢?此时我仍然认为是在之前查看的过程中忽略了什么,于是借助度娘查找到了一篇虽然没有解决我的问题但是同样让我受益匪浅的文章,一个由session.close()引发的血案(来自本站),解释了连接池方式连接数据库如果不调用sqlSession.close()方法会导致的可怕后果。

回到最开始的问题,其实可疑目标也只剩sqlSessionFactoryBuilder.build()和sqlSessionFactory.openSession()了,从前者开始继续深入方法,来到SqlSessionFactoryBuilder类,看到如下代码

public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
    try {
      XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
      return build(parser.parse());
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error building SqlSession.", e);
    } finally {
      ErrorContext.instance().reset();
      try {
        inputStream.close();
      } catch (IOException e) {
        // Intentionally ignore. Prefer previous error.
      }
    }
  }

谢天谢地!原来这么容易就能找到,我们的IO流刚刚传进来解析完成就被人家迫不及待地关上了。

与此同时也可以看出一些SqlSessionFactoryBuilder的原理,是将解析过的xml配置信息传入了DefaultSqlSessionFactory(Configuration configuration)参数里面,返回一个SqlSessionFactory对象

代码无止境,日后继续研究


评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值