目录

在 MyBatis 中动态修改 JDBC 属性

目录


最近在写的东西打算用 Sqlite 数据库,遇到在 MyBatis 中动态指定 JDBC 属性值的需求,比如:根据用户输入的参数来指定输出的数据库文件路径。

又花了不少时间才找到实现方法,记录如下:

  • MyBatis 的 Demo 代码可以参考这位同学的 GitHub

  • 此处基于这个 Demo 来动态修改 JDBC 属性值

    • jdbc.properties

      • 1
        2
        
        jdbc.driver=org.sqlite.JDBC
        jdbc.url=jdbc:sqlite:D:\\test\\0131_mybatis_sqlite\\test0.db
        
    • sqliteMybatisTest.xml

      •  1
         2
         3
         4
         5
         6
         7
         8
         9
        10
        11
        12
        13
        
            <!-- ... -->
            <environments default="development">
                <environment id="development">
                    <!-- 当前的事务事务管理器是 JDBC -->
                    <transactionManager type="JDBC"/>
                    <!-- 数据源类型 POOLED:使用mybatis的连接池 -->
                    <dataSource type="POOLED">
                        <property name="driver" value="${jdbc.driver}"/>
                        <property name="url" value="${jdbc.url}"/>
                    </dataSource>
                </environment>
            </environments>
            <!-- ... -->
        
    • MyBatisUtil.java

      •  1
         2
         3
         4
         5
         6
         7
         8
         9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        41
        42
        43
        44
        45
        46
        47
        48
        49
        50
        51
        52
        53
        54
        55
        56
        
        package monster.helloworld.utils;
        
        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;
        import java.io.Reader;
        import java.util.Properties;
        
        public class MyBatisUtil {
        
            private static SqlSessionFactory factory = null;
        
            // 使用 static 静态代码块,只在类加载时执行一次
            static {
                try {
                    // mybatis 配置文件
                    String resource = "sqliteMybatisTest.xml";
        
        //            // InputStream 方式
        //            // 加载 MyBatis 的主配置文件
        //            InputStream inputStream = Resources.getResourceAsStream(resource);
        //            // 方式一:使用 jdbc.properties 配置文件中的属性
        //            // 通过构建器(SqlSessionFactoryBuilder)构建一个SqlSessionFactory工厂对象
        //            // factory = new SqlSessionFactoryBuilder().build(inputStream);
        //
        //            // 方式二:指定属性值,覆盖 jdbc.properties 配置文件中的属性(可以动态指定属性值)
        //            Properties properties1 = new Properties();
        //            properties1.setProperty("jdbc.url", "jdbc:sqlite:D:\\test\\0131_mybatis_sqlite\\test1.db");
        //            // factory = new SqlSessionFactoryBuilder().build(inputStream, properties1);
        //            factory = new SqlSessionFactoryBuilder().build(inputStream, null, properties1);
        
                    // Reader 方式
                    Reader reader = Resources.getResourceAsReader(resource);
                    // 方式三:
        //            factory = new SqlSessionFactoryBuilder().build(reader);
        
                    // 方式四:
                    Properties properties2 = new Properties();
                    properties2.setProperty("jdbc.url", "jdbc:sqlite:D:\\test\\0131_mybatis_sqlite\\test2.db");
        //            factory = new SqlSessionFactoryBuilder().build(reader, properties2);
                    factory = new SqlSessionFactoryBuilder().build(reader, null, properties2);
        
                    // 参考:https://blog.csdn.net/zht666/article/details/20220849
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        
            public static SqlSession getSqlSession() throws IOException {
                return factory.openSession();
            }
        }
        
    • 换成其他数据库也可以这样实现

    • 参考:

      1. https://blog.csdn.net/zht666/article/details/20220849

      2. 官方文档

        • 如果一个属性在不只一个地方进行了配置,那么,MyBatis 将按照下面的顺序来加载:

          • 首先读取在 properties 元素体内指定的属性。
          • 然后根据 properties 元素中的 resource 属性读取类路径下属性文件,或根据 url 属性指定的路径读取属性文件,并覆盖之前读取过的同名属性。
          • 最后读取作为方法参数传递的属性,并覆盖之前读取过的同名属性。

          因此,通过方法参数传递的属性具有最高优先级,resource/url 属性中指定的配置文件次之,最低优先级的则是 properties 元素中指定的属性。

        • 也就是 new SqlSessionFactoryBuilder().build(Reader/InputStream, Properties) 方法传进去的 Properties 优先级最高,其次是独立的 jdbc.properties 属性文件,最后才是 MyBatis 的核心配置文件(XML)中指定的属性。

相关内容