MyBatis 学习笔记 -- 01 第一个 MyBatis 应用

2017-06-14 15:54

创建用户表并插入一些简单的测试数据

CREATE TABLE sys_user (
  id INT(11) NOT NULL AUTO_INCREMENT,
  login_name VARCHAR(50) NOT NULL,
  real_name VARCHAR(50) NOT NULL,
  password VARCHAR(50) NOT NULL,
  PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

INSERT INTO sys_user(login_name, real_name, password)
VALUE ('admin', '系统管理员', '123456');
INSERT INTO sys_user(login_name, real_name, password)
VALUE ('test', '测试人员', '123456');

创建一个 Maven 项目

修改 pom.xml 文件,添加如下依赖:

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.4</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.22</version>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.25</version>
</dependency>

创建 log4j.properties

Log4J 配置文件,放在 classpath 路径下。

log4j.rootLogger=INFO,console
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{HH:mm:ss,SSS} %p %c {%L} - %m%n

创建 mybatis-config.xml

MyBatis 配置文件,用于配置数据库连接、SQL 映射文件、类型别名等,放在 classpath 路径下。

<?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>
    <typeAliases>
        <typeAlias type="demo.domain.User" alias="User"/>
    </typeAliases>
    <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="abc123"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="demo/mapper/UserMapper.xml"/>
    </mappers>
</configuration>

创建 UserMapper.xml

SQL 映射文件。

<?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="demo.dao.UserDao">
    <sql id="columns">
        s.id,
        s.login_name AS loginName,
        s.real_name AS realName,
        s.password
    </sql>
    <select id="getById" parameterType="int" resultType="User">
        SELECT <include refid="columns"/> FROM sys_user s WHERE id = #{id}
    </select>
    <select id="list" resultType="User">
        SELECT <include refid="columns"/> FROM sys_user s
    </select>
</mapper>

创建 MyBatisSqlSessionFactory.java (单例)

MyBatisSqlSessionFactory.java 用于实例化 SqlSessionFactory 单例对象。

package demo.util;

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 MyBatisSqlSessionFactory {

    private static SqlSessionFactory sqlSessionFactory;

    public static SqlSessionFactory getSqlSessionFactory() {
        if (sqlSessionFactory == null) {
            InputStream inputStream;
            try {
                inputStream = Resources.getResourceAsStream("mybatis-config.xml");
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            } catch (IOException e) {
                throw new RuntimeException(e.getCause());
            }
        }
        return sqlSessionFactory;
    }

    public static SqlSession openSqlSessioin() {
        return getSqlSessionFactory().openSession();
    }
}

创建 User.java

package demo.domain;

public class User {

    private Integer id;
    private String loginName;
    private String realName;
    private String password;

    public User() {}

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getLoginName() {
        return loginName;
    }

    public void setLoginName(String loginName) {
        this.loginName = loginName;
    }

    public String getRealName() {
        return realName;
    }

    public void setRealName(String realName) {
        this.realName = realName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", loginName='" + loginName + '\'' +
                ", realName='" + realName + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

创建 UserDao.java (接口)

package demo.dao;

import demo.domain.User;

import java.util.List;

public interface UserDao {

    /**
     * 根据 id 获取对应用户信息
     */
    User getById(Integer id);

    /**
     * 获取所有用户信息
     */
    List<User> list();
}

创建 UserService.java

package demo.service;

import demo.dao.UserDao;
import demo.domain.User;
import demo.util.MyBatisSqlSessionFactory;
import org.apache.ibatis.session.SqlSession;

import java.util.List;

public class UserService {

    /**
     * 根据 id 获取对应用户信息
     */
    public User getById(Integer id) {
        SqlSession sqlSession = MyBatisSqlSessionFactory.openSqlSessioin();
        try {
            UserDao userDao = sqlSession.getMapper(UserDao.class);
            return userDao.getById(id);
        } finally {
            sqlSession.close();
        }
    }

    /**
     * 获取所有用户信息
     */
    public List<User> list() {
        SqlSession sqlSession = MyBatisSqlSessionFactory.openSqlSessioin();
        try {
            UserDao userDao = sqlSession.getMapper(UserDao.class);
            return userDao.list();
        } finally {
            sqlSession.close();
        }
    }
}

创建 UserServiceTest.java

package demo.service;

import demo.domain.User;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

import java.util.List;

public class UserServiceTest {

    private static UserService userService;

    @BeforeClass
    public static void setup() {
        userService = new UserService();
    }

    @AfterClass
    public static void tearDown() {
        userService = null;
    }

    @Test
    public void testList() {
        List<User> users = userService.list();
        Assert.assertNotNull(users);
        for (User user : users) {
            System.out.println(user);
        }
    }
}

运行结果:

User{id=1, loginName='admin', realName='系统管理员', password='123456'}
User{id=2, loginName='test', realName='测试人员', password='123456'}

总结

There should be only one instance of SqlSessionFactoryper database environment, so we have used a singleton pattern to have only one instance of SqlSessionFactory.

Each thread should have its own instance of SqlSession. Instances of SqlSession objects are not thread safe and should not be shared. So the best scope for SqlSessionis the method scope. From a web application perspective, SqlSession should have a request scope.