[mybatis]一睹MyBatis的尊容

Posted 爱折腾的稻草

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[mybatis]一睹MyBatis的尊容相关的知识,希望对你有一定的参考价值。

No.1 mybatis简介

MyBatis是一款优秀的持久层框架,它支持定制化SQL、存储过程以及高级映射。MyBatis避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。

No.2 初体验

2.1、构建Maven项目
2.2、添加依赖

我们使用mybatis来操作mysql数据库数据,因此需要引入mybatis和mysql驱动相关的依赖包,具体代码如下:

<dependencies>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.4.6</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.18</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
</dependencies>
2.3、数据库准备

新建一个数据库名为mybatis,在该库中创建一张系统用户表(sys_user),脚本如下:

-- ----------------------------
-- Table structure for sys_user
-- ----------------------------
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` (
  `id` tinyint(20NOT NULL AUTO_INCREMENT COMMENT '主键',
  `loginName` varchar(50DEFAULT NULL COMMENT '登录账户',
  `loginPwd` varchar(50DEFAULT NULL COMMENT '登录密码',
  `createTime` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
  PRIMARY KEY (`id`)
ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;

添加测试数据,具体代码如下:

INSERT INTO `mybatis`.`sys_user` (`id``loginName``loginPwd``createTime`VALUES ('2''肖继龙''1''2018-07-18 14:21:39');
2.4、编写java实体类

定义sys_user表所对应的实体类UserEntity,具体代码如下:

/**  
 * <p>Title: UserEntity</p>  
 *
 * <p>Description: 用户实体类,对应数据库表sys_user</p>  
 *
 * @author jilong.xiao  
 * @date 2018年7月18日  
 */

public class UserEntity {
    private long id ;
    private String loginName;
    private String loginPwd;
    private Date createTime;

    getter/setter方法略...
    toString方法略...
}
2.5、定义SQL映射文件

mybatis是通过在一个 XML 映射文件,来定义要执行的SQL语句的,在本示例程序中,我们需要定一个sys_user表所对应的一个SQL操作映射文件UserMapper.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">
<!-- 为这个mapper指定一个唯一的namespace,namespace的值习惯上设置成包名+sql映射文件名,这样就能够保证namespace的值是唯一的 
    例如namespace="io.xiaojl.mapper.UserMapper"就是io.xiaojl.mapper(包名)+UserMapper(UserMapper.xml文件去除后缀) -->

<mapper namespace="io.xiaojl.mapper.UserMapper">
    <!-- 在select标签中编写查询的SQL语句, 设置select标签的id属性为getUser,id属性值必须是唯一的,不能够重复 使用parameterType属性指明查询时使用的参数类型,resultType属性指明查询返回的结果集类型 
        resultType="io.xiaojl.entity.UserEntity"就表示将查询结果封装成一个User类的对象返回 User类就是users表所对应的实体类 -->

    <!-- 根据id查询得到一个user对象 -->
    <select id="selectById" parameterType="long" resultType="io.xiaojl.entity.UserEntity">
        select * from sys_user where id=#{id}
    </select>
</mapper>
2.6、构建SqlSessionFactory

在mybaits应用中都是以一个SqlSessionFactory实例为中心,通过SqlSessionFactory可以SqlSession实例,SqlSession 完全包含了面向数据库执行 SQL 命令所需的所有方法。

构建SqlSessionFactory主要有以下两种方式:

  • Mybatis配置文件的形式  
    从XML文件中构建SqlSessionFactory的实例非常简单,可以在classpath路径下添加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="com.mysql.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis" />
                <property name="username" value="root" />
                <property name="password" value="root" />
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!-- 注册Mapper文件 -->
        <mapper resource="io/xiaojl/mapper/UserMapper.xml" />
    </mappers>
</configuration>

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

然后编写构建SqlSessionFactory的方法,具体代码如下:

/**
 * <p>Title: buildSqlSessionFactory</p>  
 *
 * <p>Description: 从 XML 中构建 SqlSessionFactory</p>  
 *
 * @return
 */

public static SqlSessionFactory buildSqlSessionFactory(){
    try {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        return sqlSessionFactory;
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }
}
  • javaCode的形式  
    为了减少项目中出现xml配置文件,我们可以采用java编码的方式来构建SqlSessionFactory,我们创建一个configuration类,具体代码如下:

/**
 * <p>Title: buildSqlSessionFactoryWithConfiguration</p>  
 *
 * <p>Description: 从 configuration 中构建 SqlSessionFactory</p>  
 *
 * @return
 */

public static SqlSessionFactory buildSqlSessionFactoryWithConfiguration(){
    DataSourceFactory sdf = new PooledDataSourceFactory();
    Properties props = new Properties();
    props.put("driver""com.mysql.jdbc.Driver");
    props.put("url""jdbc:mysql://localhost:3306/mybatis");
    props.put("username""root");
    props.put("password""root");
    sdf.setProperties(props);
    DataSource dataSource = sdf.getDataSource();
    TransactionFactory transactionFactory = new JdbcTransactionFactory();
    Environment environment = new Environment("development", transactionFactory, dataSource);
    Configuration configuration = new Configuration(environment);
    //添加mapper接口类,它会自动关联并加载UserMapper.xml文件
    configuration.addMapper(UserMapper.class);
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);

    return sqlSessionFactory;
}
2.7、编写一个单元测试

经过上面一步步的搭建,基本工作已经完成,我们先编写一个单元测试,具体代码如下:

/**  
 * <p>Title: UserMapperTest</p>  
 *
 * <p>Description: 单元测试类</p>  
 *
 * @author jilong.xiao  
 * @date 2018年7月18日  
 */

public class UserMapperTest {
    @Test
    public void test_selectById(){
        //使用javacode的方法来构建SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = MybaitsConfig.buildSqlSessionFactoryWithConfiguration();
        //创建能执行映射文件中sql的sqlSession
        SqlSession session = sqlSessionFactory.openSession();
        //映射sql的标识字符串statement = mapper.xml文件中的namespace + select标签的id属性值
        String statement = "io.xiaojl.mapper.UserMapper.selectById";
        //执行查询返回一个唯一user对象的sql
        UserEntity user = session.selectOne(statement, 2L);

        System.out.println(user);
    }
}
2.8、运行

运行上述单元测试,根据Id查询用户信息,执行结果如下:

UserEntity [id=2, loginName=肖继龙, loginPwd=1, createTime=Wed Jul 18 14:21:39 CST 2018]

看到打印出了用户数据,那恭喜您,这表示mybatis正常工作了。

No.3 总结

在上面的示例程序中,我们只是简单的构建起应用,但这并不是最佳实践。

3.1、命名空间

命名空间(Namespaces)在之前版本的 MyBatis 中是可选的,这样容易引起混淆因此毫无益处。现在命名空间则是必须的,且意于简单地用更长的完全限定名来隔离语句。
出于长远考虑,使用命名空间,并将它置于合适的 Java 包命名空间之下,你将拥有一份更加整洁的代码并提高了 MyBatis 的可用性。

3.2、命名解析

为了减少输入量,MyBatis 对所有的命名配置元素(包括语句,结果映射,缓存等)使用了如下的命名解析规则:

  • 完全限定名(比如“io.xiaojl.UserMapper.selectById”)将被直接查找并且找到即用。  

  • 短名称(比如“selectById”)如果全局唯一也可以作为一个单独的引用。如果不唯一,有两个或两个以上的相同名称(比如“io.xiaojl.UserMapper.selectById”和“io.xiaojl.RoleMapper.selectById”),那么使用时就会收到错误报告说短名称是不唯一的,这种情况下就必须使用完全限定名。

3.3、作用域和生命周期

依赖注入框架(比如说Spring的IOC容器)可以创建线程安全的、基于事务的 SqlSession 和映射器(mapper)并将它们直接注入到你的 bean 中,因此可以直接忽略它们的生命周期。

  • SqlSessionFactoryBuilder  
    这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。
    你可以重用 SqlSessionFactoryBuilder 来创建多个 SqlSessionFactory 实例,但是最好还是不要让其一直存在以保证所有的 XML 解析资源开放给更重要的事情。

  • SqlSessionFactory  
    SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由对它进行清除或重建。
    使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建 SqlSessionFactory 被视为一种“坏代码”。
    因此 SqlSessionFactory 的最佳作用域是应用作用域。有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。

  • SqlSession
    每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。
    绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。也绝不能将 SqlSession 实例的引用放在任何类型的管理作用域中,比如 Servlet 架构中的 HttpSession。
    如果你现在正在使用一种 Web 框架,要考虑 SqlSession 放在一个和 HTTP 请求对象相似的作用域中。换句话说,每次收到的 HTTP 请求,就可以打开一个 SqlSession,返回一个响应,就关闭它。
    这个关闭操作是很重要的,你应该把这个关闭操作放到 finally 块中以确保每次都能执行关闭。下面的示例就是一个确保 SqlSession 关闭的标准模式:

SqlSession session = sqlSessionFactory.openSession();
try {
  // do work
finally {
  session.close();
}
  • 映射器实例(Mapper Instances)
    映射器是一个你创建来绑定你映射的语句的接口。映射器接口的实例是从 SqlSession 中获得的。
    因此从技术层面讲,任何映射器实例的最大作用域是和请求它们的 SqlSession 相同的。尽管如此,映射器实例的最佳作用域是方法作用域。也就是说,映射器实例应该在调用它们的方法中被请求,用过之后即可废弃。
    并不需要显式地关闭映射器实例,尽管在整个请求作用域(request scope)保持映射器实例也不会有什么问题,但是很快你会发现,像 SqlSession 一样,在这个作用域上管理太多的资源的话会难于控制。
    所以要保持简单,最好把映射器放在方法作用域(method scope)内。下面的示例就展示了这个实践:

SqlSession session = sqlSessionFactory.openSession();
try {
  UserMapper mapper = session.getMapper(UserMapper.class);
  // do work
finally {
  session.close();
}

小结

本文旨在带领大家快速构建一个使用Mybatis做持久层框架的应用,体验Mybatis给我们开发所带来的改变。

·end·

—如果喜欢,快分享给你的朋友们吧—

我们一起愉快的玩耍吧



以上是关于[mybatis]一睹MyBatis的尊容的主要内容,如果未能解决你的问题,请参考以下文章

mybatis学习(39):动态sql片段

SSM-MyBatis-05:Mybatis中别名,sql片段和模糊查询加getMapper

mybatis动态sql片段与分页,排序,传参的使用

MYBATIS05_ifwherechoosewhentrimsetforEach标签sql片段

MyBatis动态SQL标签用法

MyBatis高级特性