侧边栏壁纸
博主头像
张种恩的技术小栈博主等级

绿泡泡:___zze,添加备注来意

  • 累计撰写 748 篇文章
  • 累计创建 65 个标签
  • 累计收到 39 条评论

目 录CONTENT

文章目录

MyBatis(1)之入门

zze
zze
2017-11-07 / 0 评论 / 0 点赞 / 422 阅读 / 17791 字

介绍

学 MyBatis 的原因

1、目前最主流的持久层框架为 Hibernate 与 MyBatis,而且国内公司目前使用 Mybatis 的要比 Hibernate 要多。

2、Hibernate 学习门槛不低,且精通门槛更高。门槛高在如何设计 O/R 映射,在性能和对象模型之间如何权衡取得平衡,以及怎样用好 Hibernate 缓存与数据加载策略方面需要经验和能力都很强才行。

3、SQL 优化方面,Hibernate 的查询会将表中的所有字段查询出来,这一点会有性能消耗。当然,Hibernate 也可以自己写 SQL 来指定需要查询的字段,但这样就破坏了 Hibernate 开发的间接性。说得更深入一点,如果有个查询要关联多张表,而且我们要取的只是几张表中的部分字段。这时用 Hibernate 就会有些力不从心,就算用 Hibernate 的 SQLQuery,后续的维护工作也会很麻烦。

Jdbc 存在的问题

先回顾一下【Jdbc 的简单使用】,我们可以看到它存在以下问题:

  1. 频繁创建和打开、关闭数据库连接,太消耗资源。
  2. SQL 语句及参数存在硬编码,不利于维护。
  3. 结果集获取与封装复杂,存在硬编码,不利于维护。

MyBatis 介绍

MyBatis 本是 apache 的一个开源项目 iBatis,2010 年这个项目由 Apache software foundation 迁移到了 Google code,并改名为 iBatis。2013 年 11 月迁移到 Github。

MyBatis 是面向 SQL 的持久层框架,它封装了 jdbc 访问数据库的过程,我们开发时,只需要专注于 SQL 语句本身的拼装,其它复杂的过程全部可以交给 MyBatis 去完成。

官方文档地址:http://www.mybatis.org/mybatis-3/zh/configuration.html

image.png

入门程序

搭建

1、使用 Maven 创建 Java 工程,依赖如下:

<!-- pom.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.zze</groupId>
    <artifactId>mybatis_test1</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.25</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.25</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.2.8</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.0-rc1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.0-rc1</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <dependency>
            <groupId>javassist</groupId>
            <artifactId>javassist</artifactId>
            <version>3.11.0.GA</version>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.1.1</version>
        </dependency>
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>2.2.2</version>
        </dependency>
        <dependency>
            <groupId>asm</groupId>
            <artifactId>asm</artifactId>
            <version>3.3.1</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.37</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.6.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

2、创建 Jdbc 连接属性文件:

jdbc.url=jdbc:mysql://192.168.208.192:3306/test?characterEncoding=utf-8
jdbc.driver=com.mysql.jdbc.Driver
jdbc.username=root
jdbc.password=root

3、创建与数据库表对应的 POJO:

<!-- com.zze.mybatis.pojo.User -->
import java.util.Date;

public class User {
    private Integer id;
    private String name;
    private Integer age;
    private Date birthday;
    private String uuid;

    public Integer getId() {
        return id;
    }

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

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getUuid() {
        return uuid;
    }

    public void setUuid(String uuid) {
        this.uuid = uuid;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", birthday=" + birthday +
                '}';
    }
}

4、创建 POJO 对应映射文件:

<!-- mybatis/mapper/User.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="user">
 
</mapper>

5、创建 MyBatis 核心配置文件:

<!-- mybatis/SqlMapConfig.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>
    <!-- 加载属性文件 -->
    <properties resource="jdbc.properties"/>
    <!-- 和spring整合后 environments配置将废除-->
    <environments default="development">
        <environment id="development">
            <!-- 使用jdbc事务管理-->
            <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="mybatis/mapper/User.xml"/>
    </mappers>
</configuration>

6、创建 Log4j 属性文件:

# log4j.properties
log4j.rootLogger = debug,stdout,E

### 输出信息到控制抬 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n

### 输出DEBUG 级别以上的日志到=E://logs/error.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = E://logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

### 输出ERROR 级别以上的日志到=E://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =E://logs/error.log 
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR 
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

测试

1、抽取工具类:

// com.zze.mybatis.util.SqlSessionFactoryUtil

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 SqlSessionFactoryUtil {
    private static SqlSessionFactory sqlSessionFactory;

    static {
        // 创建 SqlSessionFactoryBuilder 对象
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        // 创建核心配置文件的输入流
        InputStream resourceAsStream = null;
        try {
            resourceAsStream = Resources.getResourceAsStream("mybatis/SqlMapConfig.xml");
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 创建 Session 工厂
        sqlSessionFactory = sqlSessionFactoryBuilder.build(resourceAsStream);
    }

    /**
     * 打开一个 Session
     *
     * @return SqlSession 实例
     */
    public static SqlSession openSession() {
        return sqlSessionFactory.openSession();
    }

    /**
     * 打开一个 Session
     *
     * @param autoCommit 是否自动提交事务
     * @return SqlSession 实例
     */
    public static SqlSession openSession(Boolean autoCommit) {
        return sqlSessionFactory.openSession(autoCommit);
    }
}

2、修改映射文件:

<!-- mybatis/mapper/User.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="user">
    <!--
     新增操作
        parameterType : 参数类型
            selectKey 配置主键返回
                keyProperty : 主键属性
                resultType : 主键数据类型
                order : 指定 selectKey 何时执行
     -->
    <insert id="add1" parameterType="com.zze.mybatis.pojo.User">

        <selectKey keyProperty="id" resultType="int" order="AFTER">
            SELECT LAST_INSERT_ID();
        </selectKey>
        INSERT INTO user(name,age,birthday) VALUES(#{name},#{age},#{birthday});
    </insert>
    <!--
    新增操作
        useGeneratedKeys : 使用自增
        keyProperty : 指定主键属性,与 useGeneratedKeys 搭配使用
        用这两个属性相当于 add1 中使用 selectKey
    -->
    <insert id="add2" parameterType="com.zze.mybatis.pojo.User" useGeneratedKeys="true" keyProperty="id">
        INSERT INTO user(name,age,birthday) VALUES(#{name},#{age},#{birthday});
    </insert>

    <!--
    新增操作
    在真正执行插入操作之前生成一个 uuid 赋值给指定属性
    -->
    <insert id="add3" parameterType="com.zze.mybatis.pojo.User">
        <selectKey keyProperty="uuid" resultType="string" order="BEFORE">
            select UUID();
        </selectKey>
        INSERT INTO user(name,age,birthday,uuid) VALUES(#{name},#{age},#{birthday},#{uuid});
    </insert>

    <!--
    更新操作
    -->
    <update id="update" parameterType="com.zze.mybatis.pojo.User">
        UPDATE user SET name=#{name},age=#{age},birthday=#{birthday} WHERE id=#{id};
    </update>
    <!--
    获取单个对象
    -->
    <select id="getById" parameterType="int" resultType="com.zze.mybatis.pojo.User">
        SELECT id,name,age,birthday FROM user where id=#{id};
    </select>

    <!--
    根据名字模糊查询方式一
         #{} 方式相当于 jdbc 的 ? 占位符方式
         当传入参数为基础类型,使用 #{任意变量名},来引用传入的参数
    -->
    <select id="getByName1" parameterType="string" resultType="com.zze.mybatis.pojo.User">
        SELECT id,name,age,birthday FROM user where name like #{name};
    </select>

    <!--
    根据名字模糊查询方式二
         该方式为字符串拼接
         当传入的参数为基础类型时,只可以使用 ${value} 来引用传入参数
         当传入的参数为 POJO 时,直接使用${属性名}
    -->
    <select id="getByName2" parameterType="string" resultType="com.zze.mybatis.pojo.User">
        SELECT id,name,age,birthday FROM user where name like '%${value}%';
    </select>

    <!--
    查询所有
    -->
    <select id="getAll" resultType="com.zze.mybatis.pojo.User">
        SELECT id,name,age,birthday FROM user
    </select>
    <!--
    删除操作
    -->
    <delete id="deleteById" parameterType="int">
        DELETE FROM user WHERE id=#{id}
    </delete>
</mapper>

3、编写测试类测试:

// com.zze.mybatis.test.MyBatisTest
import com.zze.mybatis.pojo.User;
import com.zze.mybatis.util.SqlSessionFactoryUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

public class MyBatisTest {

    /**
     * 新增操作
     */
    @Test
    public void testAdd() throws Exception {
        SqlSession sqlSession = SqlSessionFactoryUtil.openSession(true);
        // 要新增的对象
        User user = new User();
        user.setName("张三");
        user.setAge(19);
        Date birthday = new SimpleDateFormat("yyyy-MM-dd").parse("1998-1-1");
        user.setBirthday(birthday);
        // 执行新增操作
        // 第一个参数为映射文件中的 sql id
        // 第二个参数为要传入 sql 中的参数
        // 返回影响数据条数
        // int insert = sqlSession.insert("user.add1", user);    // selectKey 方式
        // int insert = sqlSession.insert("user.add2", user);    // useGeneratedKeys 方式
        int insert = sqlSession.insert("user.add3", user); // uuid 方式
        System.out.println(user);
        // 释放资源
        sqlSession.close();
    }

    /**
     * 更新操作
     */
    @Test
    public void testUpdate() throws ParseException {
        SqlSession sqlSession = SqlSessionFactoryUtil.openSession(true);
        User user = new User();
        user.setId(4);
        user.setName("李四");
        user.setAge(45);
        user.setBirthday(new SimpleDateFormat("yyyy-MM-dd").parse("1997-4-4"));
        // 返回影响数据条数
        int update = sqlSession.update("user.update", user);
        sqlSession.close();
    }

    @Test
    public void testGetById() {
        SqlSession sqlSession = SqlSessionFactoryUtil.openSession();
        User user = (User) sqlSession.selectOne("getById", 4);
        System.out.println(user);
        sqlSession.close();
    }

    /**
     * 模糊查询方式一
     */
    @Test
    public void testGetByName1() {
        SqlSession sqlSession = SqlSessionFactoryUtil.openSession();
        List<User> objects = sqlSession.selectList("user.getByName1", "%三%");
        objects.forEach(p -> System.out.println(p));
        sqlSession.close();

        /*
        ==>  Preparing: SELECT id,name,age,birthday FROM user where name like ?
        ==> Parameters: %三%(String)
        */
    }

    /**
     * 模糊查询方式二
     */
    @Test
    public void testGetByName2() {
        SqlSession sqlSession = SqlSessionFactoryUtil.openSession();
        List<User> users = sqlSession.selectList("user.getByName2", "三");
        users.forEach(u -> System.out.println(u));
        sqlSession.close();

        /*
        ==>  Preparing: SELECT id,name,age,birthday FROM user where name like '%三%'
         */
    }

    /**
     * 查询所有
     */
    @Test
    public void testGetAll() {
        SqlSession sqlSession = SqlSessionFactoryUtil.openSession();
        List<Object> users = sqlSession.selectList("getAll");
        users.forEach(u -> System.out.println(u));
        sqlSession.close();
    }

    /**
     * 删除操作
     */
    @Test
    public void testDelete(){
        SqlSession sqlSession = SqlSessionFactoryUtil.openSession(true);
        // 返回影响数据条数
        int delete = sqlSession.delete("user.deleteById", 3);
        sqlSession.close();
    }
}
0

评论区