MyBatis的使用和配置


MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 有以下特点:

  • 简单易学,小且简单:没有第三方依赖,最简单安装只要两个jar包+配置几个sql映射文件,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
  • 灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。
  • 解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
  • 提供映射标签,支持对象与数据库的orm字段关系映射
  • 提供对象关系映射标签,支持对象关系组建维护
  • 提供xml标签,支持编写动态sql。

一、快速入门实例

1、引用依赖

单独使用 mybatis,只需引入mybatis-x.x.x.jar 和相关的数据库连接包就行。

使用 maven 的 dependency 配置为

<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>3.4.6</version>
</dependency>

我的例子的应用目录结构为下图

2、mybatis配置和 xml映射文件配置

每个基于 MyBatis 的应用都是以一个SqlSessionFactory的实例为中心的。

SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder获得。

SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先定制的 Configuration 的实例构建出 SqlSessionFactory 的实例。

1)mybatis XML 配置

MyBatis 的XML配置文件(configuration XML)中包含了对 MyBatis 系统的核心设置,包含获取数据库连接实例的数据源(DataSource)和决定事务作用域和控制方式的事务管理器(TransactionManager)

这里先给出一个用 xml 配置的简单示例 mybatis-config.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>

  <!-- 环境配置:事务管理器和数据源配置 -->
  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC" />
      <dataSource type="POOLED">
        <property name="driver" value="${jdbc.driver}" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
      </dataSource>
    </environment>
  </environments>

  <!-- 映射器 -->
  <mappers>
    <mapper resource="com/brave/dao/mapper/UpmsUserMapper.xml" />
  </mappers>
</configuration>

数据源属性文件 database.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/shiyu?autoReconnect=true&useUnicode=true&characterEncoding=utf-8
jdbc.username=zou
jdbc.password=******

通过配置文件我们可以从中构建 SqlSessionFactory 的实例

inputStream = Resources.getResourceAsStream("conf/mybatis-config.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

2) xml映射文件配置

我们从上面的配置可以看到有映射器的配置

<mapper resource="com/brave/dao/mapper/UpmsUserMapper.xml" />

这里先给出该映射文件示例

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  
 <!--- 命名空间 namespace -->
<mapper namespace="com.brave.dao.UpmsUserDao">

    <!-- 结果集映射 -->
    <resultMap type="com.brave.model.UpmsUser" id="upmsUser">
        <id column="user_id" property="userId"/>
        <result column="loginname" property="loginname"/>
        <result column="password" property="password"/>
        <result column="realname" property="realname"/>
        <result column="phone" property="phone"/>
        <result column="email" property="email"/>
        <result column="is_locked" property="locked"/>
        <result column="gmt_create" property="gmtCreate"/>
        <result column="gmt_modified" property="gmtModified"/>
    </resultMap>
    <!-- 查询sql -->
    <select id="selectOne" resultMap="upmsUser">
        select * from upms_user where user_id = #{userId}
    </select>

    <select id="selectUser" resultMap="upmsUser">
        select * from upms_user
    </select>
    
    <insert id="insertUser">
        insert into upms_user (user_id,loginname,password,realname,is_locked)
        value(#{userId},#{loginname},#{password},#{realname},#{locked})
    </insert>

</mapper>

上面我们通过 mybatis配置xml 构建了SqlSessionFactory,有了 SqlSessionFactory,顾名思义,我们就可以从中获得 SqlSession 的实例了。SqlSession 完全包含了面向数据库执行 SQL 命令所需的所有方法。你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句:

SqlSession sqlSession = sqlSessionFactory.openSession();
try {
    //这里我们通过 命名空间+sql语句的Id来执行映射的sql语句
    UpmsUser upmsUser = sqlSession.selectOne("com.brave.dao.UpmsUserDao.selectOne", 10001L);
}finally {
    sqlSession.close();
}

3、构建 SqlSessionFactory,获取 SqlSession

从上面的 mybatis配置和 xml映射文件配置 我们可以了解到这样一个流程:

通过流读取 mabatis 配置文件信息,使用 SqlSessionFactoryBuilder 构建 SqlSessionFactory,再从SqlSessionFactory 中获取 SqlSession 实例,通过 SqlSession 实例来直接执行已映射的 SQL 语句

在这里我们需要理解这三个对象的不同作用域和生命周期,错误的使用会导致非常严重的并发问题。

生命周期作用域(Scope)
SqlSessionFactoryBuilder可以被实例化、使用和丢弃,一旦创建了SqlSessionFactory,就不再需要它了方法(也就是局部方法变量)
SqlSessionFactory一旦被创建就应该在应用的运行期间一直存在,没有任何理由对它进行清除或重建应用(最简单的就是使用单例模式或者静态单例模式)
SqlSession每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的请求 / 方法

因为 SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,我们可以使用单例,创建一个 SqlSessionFactoryUtil

public class SqlSessionFactoryUtil {

    private static SqlSessionFactory sqlSessionFactory;

    /**
     * 每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为中心的。
     * SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。
     * 而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先定制的 Configuration 的实例构建出 SqlSessionFactory 的实例。
     * 
     * SqlSessionFactoryBuilder 最佳作用域是方法作用域(也就是局部方法变量) 
     * SqlSessionFactory 最佳作用域是应用作用域 
     * SqlSession 最佳的作用域是请求或方法作用域
     */
    public static SqlSessionFactory getSqlSessionFactory() {
        if (sqlSessionFactory != null) {
            return sqlSessionFactory;
        }
        InputStream inputStream;
        try {
            inputStream = Resources.getResourceAsStream("conf/mybatis-config.xml");
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return sqlSessionFactory;
    }
}

我们可以创建一个 baseDao 获取 SqlSession

public class BaseDaoImpl implements BaseDao {

    @Override
    public SqlSession getSqlSession() {
        SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtil.getSqlSessionFactory();
        return sqlSessionFactory.openSession();
    }

}

通过 命名空间+sql语句的Id来执行映射的sql语句

public class UpmsUserDaoImpl extends BaseDaoImpl implements UpmsUserDao {

    @Override
    public UpmsUser selectOne(Long userId) {
        SqlSession sqlSession = getSqlSession();
        UpmsUser upmsUser = null;
        try {
            upmsUser = sqlSession.selectOne("com.brave.dao.UpmsUserDao.selectOne", userId);
        } finally {
            sqlSession.close();
        }
        return upmsUser;
    }

    @Override
    public List<UpmsUser> selectUser() {
        SqlSession sqlSession = getSqlSession();
        List<UpmsUser> upmsUsers = null;
        try {
            upmsUsers = sqlSession.selectList("com.brave.dao.UpmsUserDao.selectUser");
        } finally {
            sqlSession.close();
        }
        return upmsUsers;
    }

    @Override
    public int insertUser(UpmsUser upmsUser) {
        SqlSession sqlSession = getSqlSession();
        int n = 0;
        try {
            n = sqlSession.insert("com.brave.dao.UpmsUserDao.insertUser", upmsUser);
            sqlSession.commit();
        } finally {
            sqlSession.close();
        }
        return n;
    }
}

我们用 Junit 创建测试类测试一下结果

public class UpmsUserDaoImplTest {

     UpmsUserDao userDao = new UpmsUserDaoImpl();

    @Test
    public void testSelectOne() {
        System.out.println(userDao.selectOne(10001L).toString());
    }

    @Test
    public void testSelectUser() {
        List<UpmsUser> upmsUsers = userDao.selectUser();
        for (UpmsUser upmsUser : upmsUsers) {
            System.out.println(upmsUser.toString());
        }
    }

    @Test
    public void testInsertUser() {
        UpmsUser upmsUser = new UpmsUser();
        upmsUser.setUserId(10002L);
        upmsUser.setLoginname("zou");
        upmsUser.setPassword("123456");
        upmsUser.setLocked(false);
        int n = userDao.insertUser(upmsUser);
        System.out.println("插入" + n + "行");
    }
}

到了这里我们其实可以发现,我们在映射文件中写的 命名空间 和 完全限定名 是一样的,如com.brave.dao.UpmsUserDao ,这个命名可以直接映射到在命名空间中同名的 Mapper 类,并将已映射的 sql 语句中的名字、参数和返回类型匹配成方法

这样我们就可以像上面那样很容易地调用这个对应 Mapper 接口的方法,只需要接口,不需要写实现类。我们的接口方法名称和 映射文件中的sql语句Id一致的话可以直接调用。

UpmsUserDao.java

public interface UpmsUserDao extends BaseDao {

    UpmsUser selectOne(Long userId);

    List<UpmsUser> selectUser();

    int insertUser(UpmsUser upmsUser);
}

测试

@Test
public void testInterface() {
    SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtil.getSqlSessionFactory();
    SqlSession session = sqlSessionFactory.openSession();
    //可以直接映射到在命名空间中同名的 Mapper 类 (只要映射接口类就可以了,不需要实现)
    UpmsUserDao upmsUserDao = session.getMapper(UpmsUserDao.class);
    List<UpmsUser> upmsUsers = upmsUserDao.selectUser();
    for (UpmsUser upmsUser : upmsUsers) {
        System.out.println(upmsUser.toString());
    }
}

它们的映射的语句还可以不需要用 XML 来做,取而代之的是可以使用 Java 注解

@Select("select * from upms_user where user_id = #{userId}")
UpmsUser getUser(Long userId);

二、SqlSession 的使用和API

使用 MyBatis 的主要 Java 接口就是 SqlSession。可以通过这个接口来执行命令,获取映射器和管理事务。SqlSessions 是由 SqlSessionFactory 实例创建的。SqlSessionFactory 对象包含创建 SqlSession 实例的所有方法。而 SqlSessionFactory 本身是由 SqlSessionFactoryBuilder 创建的,它可以从 XML、注解或手动配置 Java 代码来创建 SqlSessionFactory。

三、MyBatis XML配置

MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置(settings)和属性(properties)信息。文档的顶层结构如下:

  • configuration 配置
    • properties 属性
    • settings 设置
    • typeAliases 类型别名
    • typeHandlers 类型处理器
    • objectFactory 对象工厂
    • plugins 插件
    • environments 环境
      • environment 环境变量
      • transactionManager 事务管理器
      • dataSource 数据源
    • databaseIdProvider 数据库厂商标识
    • mappers 映射器

官方的文档很详细,这里不写了,直接参考过去
http://www.mybatis.org/mybatis-3/zh/configuration.html

<?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>

    <!-- 属性配置 -->
    <!-- 优先级:方法参数传递 > resource/url 属性中指定的配置文件 > 属性中指定的属性property -->
    <properties resource="conf/database.properties">
        <property name="jdbc.username" value="zou" />
        <property name="jdbc.password" value="******" />
    </properties>

    <!-- 调整设置,它们会改变 MyBatis 的运行时行为 -->
    <settings>
        <!-- 全局的映射器开启或禁用缓存 (默认true) -->
        <setting name="cacheEnabled" value="true" />
        <!-- 全局开启或管理延迟加载。当开启时,所有关联对象都会延迟加载 (默认false) -->
        <setting name="lazyLoadingEnabled" value="true" />
        <!-- 当开启时,任何方法的调用都会加载该对象的所有属性。否则,每个属性会按需加载 (默认false) -->
        <setting name="aggressiveLazyLoading" value="true"/>
        <!-- 允许单一sql语句返回多结果集 (默认true) -->
        <setting name="multipleResultSetsEnabled" value="true" />
        <!-- 使用列标签代替列名 (默认true) -->
        <setting name="useColumnLabel" value="true" />
        <!-- 允许 JDBC 支持自动生成主键 (默认false)  -->
        <setting name="useGeneratedKeys" value="false" />
        <!-- 指定 MyBatis 应如何自动映射列到字段或属性,NONE:不隐射 PARTIAL:部分  FULL:全部  (默认PARTIAL)  -->
        <setting name="autoMappingBehavior" value="PARTIAL" />
        <!-- 配置默认的执行器, SIMPLE:普通; REUSE: 执行器会重用预处理语句(prepared statements); BATCH:执行器将重用语句并执行批量更新。-->
        <setting name="defaultExecutorType" value="SIMPLE" />
        <!-- 超时时间 -->
        <setting name="defaultStatementTimeout" value="25" />
        <!-- 为驱动的结果集获取数量(fetchSize)设置一个提示值 -->
        <setting name="defaultFetchSize" value="100" />
        <!-- 允许在嵌套语句中使用分页,如果允许使用则设置为false (默认false) -->
        <setting name="safeRowBoundsEnabled" value="false" />
        <!-- 是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。(默认false) -->
        <setting name="mapUnderscoreToCamelCase" value="false" />
        <!-- 设置本地缓存范围 session:就会有数据的共享  statement:语句范围 (这样就不会有数据的共享 ) defalut:session -->
        <setting name="localCacheScope" value="SESSION" />
        <!-- 设置但JDBC类型为空时,某些驱动程序 要指定值,default:OTHER,插入空值时不需要指定类型 -->
        <setting name="jdbcTypeForNull" value="OTHER" />
        <!-- 指定哪个对象的方法触发一次延迟加载 -->
        <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString" />
    </settings>

    <!-- 类型别名是为 Java 类型设置一个短的名字。它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余 -->
    <typeAliases>
        <typeAlias alias="Author" type="domain.blog.Author" />
        <typeAlias alias="Section" type="domain.blog.Section" />
        <typeAlias alias="Tag" type="domain.blog.Tag" />
        <!-- 也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean -->
        <!-- 会使用 Bean 的首字母小写的非限定类名来作为它的别名。 比如 domain.blog.Author 的别名为 author -->
        <package name="domain.blog"/>
    </typeAliases>
    
    <!-- 类型处理器 -->
    <typeHandlers>
        <typeHandler handler="org.mybatis.example.ExampleTypeHandler"/>
    </typeHandlers>
    
    <!-- 插件 -->
    <plugins>
      <plugin interceptor="org.mybatis.example.ExamplePlugin">
        <property name="someProperty" value="100"/>
      </plugin>
    </plugins>

    <!-- 环境配置:事务管理器和数据源配置 -->
    <!-- 尽管可以配置多个环境,每个 SqlSessionFactory 实例只能选择其一 -->
    <environments default="development">
        <environment id="development">
            <!-- JDBC – 这个配置就是直接使用了 JDBC 的提交和回滚设置 -->
            <transactionManager type="JDBC" />
            <!-- POOLED– 这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来 -->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}" />
                <property name="url" value="${jdbc.url}" />
                <property name="username" value="${jdbc.username}" />
                <property name="password" value="${jdbc.password}" />
            </dataSource>
        </environment>
    </environments>

    <!-- 插件 -->
    <plugins>
        <plugin interceptor="org.mybatis.example.ExamplePlugin">
            <property name="someProperty" value="100" />
        </plugin>
    </plugins>

    <!-- 映射器 -->
    <mappers>
        <!-- 使用相对于类路径的资源引用 -->
        <mapper resource="com/brave/dao/mapper/UpmsUserMapper.xml" />
        <!-- 使用完全限定资源定位符(URL) -->
        <mapper url="file:///var/mappers/PostMapper.xml"/>
        <!-- 使用映射器接口实现类的完全限定类名 -->
        <mapper class="org.mybatis.builder.PostMapper"/>
        <!-- 将包内的映射器接口实现全部注册为映射器 -->
        <package name="org.mybatis.builder"/>
    </mappers>

</configuration>

四、Mapper映射文件配置

MyBatis 的真正强大在于它的映射语句,也是它的魔力所在。由于它的异常强大,映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。MyBatis 就是针对 SQL 构建的,并且比普通的方法做的更好。

SQL 映射文件有很少的几个顶级元素(按照它们应该被定义的顺序):

  • cache – 给定命名空间的缓存配置。
  • cache-ref – 其他命名空间缓存配置的引用。
  • resultMap – 是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加载对象。
  • parameterMap – 已废弃!老式风格的参数映射。内联参数是首选,这个元素可能在将来被移除,这里不会记录。
  • sql – 可被其他语句引用的可重用语句块。
  • insert – 映射插入语句
  • update – 映射更新语句
  • delete – 映射删除语句
  • select – 映射查询语句

每个元素的细节见官方文档
http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html

  • 17
    点赞
  • 143
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值