Mybatis简单入门

一、MyBatis的基本组成

MyBatis的核心组件:

  • SqlSessionFactoryBuilder(构造器):它会根据配置信息(sqlMapConfig.xml)或者代码来生成SqlSessionFactory(工厂接口)。
  • SqlSessionFactory:依靠工厂来生成SqlSession(会话)。
  • SqlSession:是一个既可以发送SQL去执行并返回结果,也可以获得Mapper的接口。
  • SQL Mapper:是由Java接口和XML文件(或者注解)构成的,需要给出对应的SQL和映射规则。它负责发送SQL去执行,并返回结果。

用一张图表达它们之间的关联:
Mybatis简单入门_第1张图片

1.1 构建SqlSessionFactory

每个MyBatis的应用都是以SqlSessionFactory的实例为中心的。SqlSessionFactory的实例可以通过SqlSessionFactoryBuilder获得。SqlSessionFactory是一个工厂接口,它的任务是创建SqlSession。SqlSession类似于一个JDBC的Connection对象。MyBatis提供了两种模式去创建SqlSessionFactory:一种是XML配置的方法,一种是编码方式,推荐使用XML配置的方式

所以就需要一个主配置文件sqlMapConfig.xml,用来进行数据库的相关配置。SqlSessionFactoryBuilder就根据sqlMapConfig.xml,通过SqlSessionFactoryBuilder的build方法来创建来创建SqlSessionFactory。
Mybatis简单入门_第2张图片

可以看出,build方法分为两类,一类是使用字符流,读取sqlMapConfig.xml,另一类是使用字节来读取。
查看源码会发现,最终都会调用:

    public SqlSessionFactory build(Configuration config) {
        return new DefaultSqlSessionFactory(config);
    }

其中config就是通过流读取的配置文件所对应的对象,DefaultSqlSessionFactory是SqlSessionFactory的实现类

下面以XML方式为例,构建一个SqlSessionFactory

先来创建sqlMapConfig.xml:



<configuration>
    <properties resource="db.properties"/>

    
    <typeAliases>
        <typeAlias type="com.xiaowen.pojo.User" alias="User"/>
    typeAliases>

    <environments default="development">
        <environment id="development">
            
            <transactionManager type="JDBC" />
            
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}" />
                <property name="url"
                          value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
                <property name="username" value="root" />
                <property name="password" value="root" />
            dataSource>
        environment>
    environments>
    
    <mappers>
        <mapper resource="com/xiaowen/pojo/User.xml"/>
     mappers>
configuration>

对上面的配置做一下说明:
(1)、这里配置了一个别名User,它代表com.xiaowen.pojo.User,这样我们就可以在MyBatis上下文中引用它了。
(2)、配置了环境内容,默认使用id时development的环境配置,包含以下两方面内容:

  • 代用JDBC的事务管理模式
  • 数据库的连接信息

(3)、配置映射器
最后引入了User.xml,在User.xml配置了对User表的增删改查操作,以及从数据库返回的数据映射到哪个POJO上。
创建SqlSessionFactory的java代码:

//加载核心配置文件
String resource="sqlMapConfig.xml";
InputStream in = Resources.getResourceAsStream(resource);
//创建SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);

这里我们创建了一个XML文件输入流,用SqlSessionFactoryBuilder读取XML的信息来创建SqlSessionFactory的对象。
MyBatis的解析程序会将sqlMapConfig.xml文件配置的信息解析到Configuration类对象里面,然后利用SqlSessionFactoryBuilder读取这个对象为我们创建sqlSessionFactorty。

1.2 构建SqlSession
SqlSession接口类似于一个JDBC的Connection接口对象,SqlSession对象由SqlSessionFactory的openSession方法创建,我们需要保证每次用完正常关闭它,所以正确的做法是把关闭的SqlSession接口代码写finally语句中保证每次都会关闭SqlSession,让连接资源归还给数据库。


SqlSession的用途主要有两种
(1) 获取映射器,让映射器通过命名空间和方法名找到对应的SQL,发送给数据库执行后返回结果。
(2)直接通过命名信息去执行SQL返回结果,在SqlSession层可以通过update、insert、select、delete等方法,带上SQL的id来操作XML中配置好的SQL,从而完成我们的工作;与此同时也支持事务,通过commit,rollback方法提交或者回滚事务。

1.3 配置映射器

映射器由Java接口和XML文件(或注解)共同组成的,它的作用如下。

  • 定义参数类型
  • 描述缓存
  • 描述SQL语句
  • 定义查询结果和POJO的映射关系。

映射器的实现方式有两种,一种是通过XML文件方式实现,一种是通过代码方式实现。推荐使用XML方式,

XML文件配置方式实现Mapper

使用XML文件配置是MyBatis实现Mapper的首选方式。它由一个Java接口和一个XML文件构成。

第一步:给出Java接口:

package com.xiaowen.mapper;

import com.xiaowen.pojo.User;

public interface UserMapper {

    public User findUserById(Integer id);
}

这里定义了一个接口,它有一个方法findUserById,通过ID找到用户

第二步:给出一个映射XML文件:



<mapper namespace="com.xiaowen.mapper.UserMapper">
    <select id="findUserById" parameterType="Integer" resultType="User">
        select * from user where id = #{id}
    select>
mapper>

描述一下上面的XML文件做了什么:

  • 这个文件是我们在配置文件sqlMapConfig.xml中配置了的,所以MyBatis会读取这个配置文件,生成映射器。
  • 定义了一个命名空间为com.xiaowen.mapper.UserMapper的SQLMapper,这个命名空间和我们定义的接口的全限定名是一致的。
  • 用一个select元素定义了一个查询SQL,id为findUserById,与接口方法是一致的,而parameterType则表示我们传递给这条SQL的是一个Integer型参数,而rresultType则定义我们需要返回的数据类型,这里为User,而User是之前注册com.xiaowen.pojo.User的别名。
    User如下:
package com.xiaowen.pojo;

import java.io.Serializable;
import java.util.Date;
import java.util.List;

public class User implements Serializable {
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private Integer id;
    private String username;// 用户姓名
    private String sex;// 性别
    private Date birthday;// 生日
    private String address;// 地址


    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    @Override
    public String toString() {
        return "User [id=" + id + ", username=" + username + ", sex=" + sex
                + ", birthday=" + birthday + ", address=" + address + "]";
    }
}
  • #{id}为这条SQL的参数,可以理解为占位符。而SQL列的别名和User属性名称保持一致,那么MyBatis就会把这条语句查询的结果自动映射到我们需要的User的属性上,这就是自动映射。我们可以用SqlSession来获取这个Mapper。我们可以用SqlSession来获取这个Mapper:
    @Test
    public void fun1() throws Exception{
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserMapper userMapper = ac.getBean(UserMapper.class);
        User user = userMapper.findUserById(10);
        System.out.println(user);

    }

1.4 生命周期
SqlSessionFactoryBuilder

SqlSessionFactoryBuilder是利用XML或者Java编码获得资源来构建SqlSessionFactory的。通过它可以构建多个SessionFactory。所以它的生命周期只存在于方法的局部,它的作用就是生产SqlSessionFactory对象。

SqlSessionFactory
SqlSessionFactory的作用是创建SqlSession,而SqlSession就是一个会话,相当于JDBC的Connection对象。每次应用程序需要访问数据库,就要通过SqlSessionFactory创建SqlSession,所以SqlSession应该在MyBatis应用的整个生命周期中。而如果我们多次创建同一个数据库的SqlSessionFactory,会打开更多的连接资源,因此SqlSessionFactory的责任是唯一的,它的责任就是创建SqlSession,所以应该采用单例模式,一个数据库值对应一个SqlSessionFactory,管理好数据库资源的分配,避免过多的Connection被消耗。

SqlSession
SqlSession是一个会话,相当于JDBC的connection对象,它的生命周期应该是在请求数据库处理事务的过程中。它是一个线程不安全的对象,在涉及多线程的时候,要注意其隔离级别。此外,每次创建的SqlSession都必须及时关闭它。

Mapper
Mapper是一个接口,而且没有任何实现类,它的作用是发送SQL,然后返回我们需要的结果,或者执行SQL从而修改数据库的数据,因此它应该在一个SqlSession事务方法之内,是一个方法级别的东西。它就如同JDBC中的一条SQL语句的执行,它最大的范围和SqlSession是相同的。

二、实例
POJO:与数据库中的表对应:
User

package com.xiaowen.pojo;

import java.io.Serializable;
import java.util.Date;
import java.util.List;

public class User implements Serializable {
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private Integer id;
    private String username;// 用户姓名
    private String sex;// 性别
    private Date birthday;// 生日
    private String address;// 地址

    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    @Override
    public String toString() {
        return "User [id=" + id + ", username=" + username + ", sex=" + sex
                + ", birthday=" + birthday + ", address=" + address + "]";
    }
}

UserMapper接口:

package com.xiaowen.mapper;
import com.xiaowen.pojo.User;
public interface UserMapper {

    //遵循四个原则:
    //接口方法名== UserMapper.xml中的id名
    //返回值类型与UserMapper.xml文件中返回值类型要一致
    //方法的入参类型与UserMapper.xml中入参的类型要一致
    //命名空间与接口绑定
    public User findUserById(Integer id);
    public void insertUser(User user);
    public void updateUserById(User user);
    public void deleteUserById(Integer id);
}

UserMapper.xml与UserMapper接口进行映射:





<mapper namespace="com.xiaowen.mapper.UserMapper">
    
    <select id="findUserById" parameterType="Integer" resultType="User">
        select * from user where id = #{v}
    select>

    
    <insert id="insertUser" parameterType="User">
      <selectKey keyProperty="id" resultType="Integer" order="AFTER">
          select LAST_INSERT_ID()
      selectKey>
        insert into user (username,birthday,address,sex) values (#{username},#{birthday},#{address},#{sex})
    insert>

    
    <update id="updateUserById" parameterType="User">
        update user set username=#{username},sex=#{sex},birthday=#{birthday},address=#{address} where id=#{id}
    update>
    
    <delete id="deleteUserById" parameterType="Integer">
        delete from user where id = #{id}
    delete>
mapper>

主配置文件:



<configuration>
    <properties resource="db.properties"/>

    
    <typeAliases>
        <typeAlias type="com.xiaowen.pojo.User" alias="User"/>
    typeAliases>

    <environments default="development">
        <environment id="development">
            
            <transactionManager type="JDBC" />
            
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}" />
                <property name="url"
                          value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
                <property name="username" value="root" />
                <property name="password" value="root" />
            dataSource>
        environment>
    environments>
    
    <mappers>
        <mapper class="com.xiaowen.mapper.UserMapper"/>
     mappers>
configuration>

测试方法:

    @Test
    public void findUserById() throws Exception {
        //加载核心配置文件
        String resource = "sqlMapConfig.xml";
        InputStream in = Resources.getResourceAsStream(resource);
        //创建SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
        //创建SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //获得Mapper
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.findUserById(10);
        System.out.println(user);
        sqlSession.close();

    }

    @Test
    public void insertUser() throws Exception {
        //加载核心配置文件
        String resource = "sqlMapConfig.xml";
        InputStream in = Resources.getResourceAsStream(resource);
        //创建SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
        //创建SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //获得Mapper
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = new User();
        user.setUsername("小文");
        user.setSex("1");
        user.setAddress("南京");
        userMapper.insertUser(user);
        //如果不提交,事务会自动回滚,无法插入数据到数据库
        sqlSession.commit();
        sqlSession.close();
    }

    @Test
    public void updateUserById() throws Exception {
        //加载核心配置文件
        String resource = "sqlMapConfig.xml";
        InputStream in = Resources.getResourceAsStream(resource);
        //创建SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
        //创建SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //获得Mapper
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = new User();
        user.setUsername("小文");
        user.setSex("1");
        user.setAddress("北京");
        user.setId(31);
        userMapper.updateUserById(user);
        //如果不提交,事务会自动回滚,无法插入数据到数据库
        sqlSession.commit();
        sqlSession.close();
    }

    @Test
    public void deleteUserById() throws Exception {
        //加载核心配置文件
        String resource = "sqlMapConfig.xml";
        InputStream in = Resources.getResourceAsStream(resource);
        //创建SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
        //创建SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //获得Mapper
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        userMapper.deleteUserById(31);
        //如果不提交,事务会自动回滚,无法插入数据到数据库
        sqlSession.commit();
        //释放资源
        sqlSession.close();
    }

你可能感兴趣的:(MyBatis)