Skip to content

yaohl0911/learnMybatis

Repository files navigation

Mybatis01:Mybatis的常见用法

Mybatis02:Mybatis的常见用法 + 配置文件

Mybatis03:Mybatis的常见用法 + 配置文件 + 日志 --> 可以直接看Mybatis03

Mybatis04-ResultMap: resultMap的用法 -- 多对一查询

Mybatis04-ResultMap: resultMap的用法 -- 一对多查询

教程链接:https://www.bilibili.com/video/BV1NE411Q7Nx?p=7

初识Mybatis

学习Mybatis思路:搭建环境 -->导入框架/依赖-->编写代码-->测试

搭建MySQL环境

CREATE DATABASE `mybatis`; 

USE `mybatis`;

CREATE TABLE `users`(
	id INT NOT NULL PRIMARY KEY,
	name VARCHAR(30) DEFAULT NULL,
	age INT NOT NULL
) ENGINE=INNODB DEFAULT CHARSET=utf8;

INSERT INTO users(id, name, age) VALUES(1, 'aaa', 30);
INSERT INTO users(id, name, age) VALUES(2, 'bbb', 29);
INSERT INTO users(id, name, age) VALUES(3, 'ccc', 2);

导入Mybatis依赖

这里用Maven管理工程

注意需要把资源文件所在的目录加入到资源文件扫面路径,否则找不到资源文件。

<build>
    <!--
     Maven约定大于配置,默认只包含src/main/resources下的资源文件
     想要包含其他路径下的资源文件,需要修改Maven配置把对应的路径加进来
     -->
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering>
        </resource>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering>
        </resource>
    </resources>
</build>

Mybatis的基本应用

JDBC方式的思路

实体类

接口

实现类

Mybatis方式的思路

按照Mybatis官方教程的思路,要用Mybatis实现,首先要实现SqlSessionFactory和SqlSession等,由于是公共代码,所以提炼成一个Utils工具

package com.yaohl0911.utils;

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

    static {
        try {
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static SqlSession getSqlSession() {
        return sqlSessionFactory.openSession();
    }
}

上述代码需要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.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/yaohl0911/dao/UserMapper.xml"/>
    </mappers>
</configuration>

实体类

package com.yaohl0911.pojo;

import lombok.Data;

@Data
public class User {
    private int id;
    private String name;
    private int age;
}

Mapper接口

package com.yaohl0911.dao;


import com.yaohl0911.pojo.User;

import java.util.List;

public interface UserMapper {
    // 获取全部数据
    List<User> getUserList();

    //根据id查询数据
    User getUserByID(int id);

    // 插入一条数据
    int addUser(User user);

    // 修改一条数据
    int updateUser(User user);

    // 删除一条数据
    int deleteUser(int id);
}

Mapper配置

<?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="com.yaohl0911.dao.UserMapper">

    <select id="getUserList" resultType="com.yaohl0911.pojo.User">
        SELECT * FROM mybatis.users;
    </select>

    <select id="getUserByID" parameterType="int" resultType="com.yaohl0911.pojo.User">
        SELECT * FROM mybatis.users WHERE id=#{id};
    </select>
    <select id="getUserLike" resultType="com.yaohl0911.pojo.User">
        SELECT * FROM mybatis.users WHERE name LIKE #{valus};
    </select>

    <insert id="addUser" parameterType="com.yaohl0911.pojo.User">
        INSERT INTO mybatis.users (id, name, age) VALUE (#{id}, #{name}, #{age});
    </insert>

    <update id="updateUser" parameterType="com.yaohl0911.pojo.User">
        UPDATE mybatis.users SET name=#{name}, age=#{age} WHERE id=#{id};
    </update>

    <delete id="deleteUser" parameterType="int">
        DELETE FROM mybatis.users WHERE id=#{id};
    </delete>
</mapper>

测试

package com.yaohl0911;

import com.yaohl0911.dao.UserMapper;
import com.yaohl0911.pojo.User;
import com.yaohl0911.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;

public class TestDriver {
    @Test
    public void getUserListTest() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = userMapper.getUserList();
        for (User user : userList) {
            System.out.println(user);
        }
        sqlSession.close();
    }

    @Test
    public void getUserByIDTest() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.getUserByID(1);
        System.out.println("Add user: " + user.toString());
        sqlSession.close();
    }

    @Test
    public void addUserTest() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        int res = userMapper.addUser(new User(4, "dd2", 2));
        if(res != 0) {
            System.out.println("Add user succeed.");
        }
        sqlSession.commit();
        sqlSession.close();
    }

    @Test
    public void updateUserTest() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        int res = userMapper.updateUser(new User(4, "dd2", 1));
        if(res != 0) {
            System.out.println("Update user succeed.");
        }
        sqlSession.commit();
        sqlSession.close();
    }

    @Test
    public void deleteUserTest() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        int res = userMapper.deleteUser(4);
        if(res != 0) {
            System.out.println("Delete user succeed.");
        }
        sqlSession.commit();
        sqlSession.close();
    }
}

Map的使用

使用map的方式无论是作为parameterType还是作为resultType,都比较容易定制

  • 使用map可以方便地自定义字段

    Mapper配置

    <insert id="addUser" parameterType="map">
      INSERT INTO mybatis.users (id, name, age) VALUES (#{ID}, #{NAME}, #{AGE});
    </insert>

    Mapper接口

    // 插入一条数据
    int addUser(Map<String, Object> map);

    测试代码

        @Test
        public void addUserTest() {
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("ID", 4);   // 这样就可以更方便地自定义字段了
            map.put("NAME", "dd2");
            map.put("AGE", 2);
            int res = userMapper.addUser(map);
            if(res != 0) {
                System.out.println("Add user succeed.");
            }
            sqlSession.commit();
            sqlSession.close();
        }
  • 多个参数时用map比较方便

    Mapper配置

      <select id="getUserList"  parameterType="map" resultType="user">
          SELECT * FROM mybatis.users LIMIT #{startIndex}, #{pageSize};
      </select>

    Mapper接口

    		// 获取全部限制范围内的全部数据
      	List<User> getUserList(Map<String, Object> map);

    测试代码

        @Test
        public void getUserListTest() {
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("startIndex", 0);
            map.put("pageSize", 2);
            List<User> userList = userMapper.getUserList(map);
            for (User user : userList) {
                System.out.println(user);
            }
            sqlSession.close();
        }

模糊查找

<select id="getUserLike" resultType="com.yaohl0911.pojo.User">
    select * from mybatis.users where name like #{valus};
</select>
@Test
public void getUserLikeTest() {
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    List<User> userList= userMapper.getUserLike("%d%"); // sql代码执行的时候,传递通配符"% %"
    for (User user : userList) {
        System.out.println(user);
    }

    sqlSession.close();
}

配置解析

属性优化

属性配置文件sqlconfig.properties,以key=value的形式存储,文件名随意

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis
username=root
password=123456

修改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>
  <!-- 设置属性,可以在配置文件中设置,也可以在这里设置 -->
    <properties resource="sqlconfig.properties">
    		<!-- 除了properties文件中可以写配置之外,这里也可以写一部分配置 -->
    </properties>
    <!-- 环境可以配置多套,default处选择使用哪套配置 -->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    <!-- 每一个mapper.xml都需要在Mybatis核心配置文件中注册 -->
    <mappers>
        <mapper resource="com/yaohl0911/dao/UserMapper.xml"/>
    </mappers>
</configuration>

注意:如果在sqlconfig.properties和里同时设置了某个字段,配置文件优先生效。

别名配置

直接指定别名

在配置文件合适的位置添加:

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

扫描某个包

这种用法,默认别名为首字母小写的类名,例如User类的别名是user。

<typeAliases>
    <package name="com.yaohl0911.pojo"/>
</typeAliases>

直接指定别名可以比较灵活的用任意别名,扫描包的方式不行,但是扫描包的方式可以用注解实现。

映射器配置

日志配置

定位的好手段。

Mybatis支持的日志类型:

SLF4J

LOG4J 【掌握】

LOG4J2

JDK_LOGGING

COMMONS_LOGGING

STDOUT_LOGGING 【掌握】

NO_LOGGING

在Mybatis具体使用哪一个,在设置中配置,默认未设置

使用STDOUT_LOGGING

<settings>
    <setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>

使用LOG4J

Mybatis-config.xml增加配置:

<settings>
    <setting name="logImpl" value="LOG4J"/>
</settings>__

logconfig.properties配置文件 注:文件名任意

# 将等级为DEBUG的日志信息输出到console和file这两个目的地
log4j.rootLogger = DEBUG,console,file

# 控制台输出设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold = DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n

# 文件输出设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File = ./log/log.log
log4j.appender.file.MaxFileSize = 10mb
log4j.appender.file.Threshold = DEBUG
log4j.appender.file.layout = org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n

# 日志输出级别设置
log4j.logger.org.mybatis = DEBUG
log4j.logger.java.sql = DEBUG
log4j.logger.java.sql.Statement = DEBUG
log4j.logger.java.sql.ResultSet = DEBUG
log4j.logger.java.sql.PreparedStatement = DEBUG

Mybatis进阶

ResultMap

基本用法

结果集映射,最基本的应用是解决属性名和字段名不一致的问题

    <resultMap id="userMap" type="com.yaohl0911.pojo.User">
        <result column="id" property="id"/>
        <result column="name" property="name"/> 
        <result column="nianling" property="age"/>  <!-- pojo中是age,db中是拼音,使用resultMap做映射;前边两行是一样的。不需要映射,不写也行。 -->
    </resultMap>

多对一查询

DB数据创建

CREATE DATABASE `mybatis`; 

USE `mybatis`;

CREATE TABLE `student`(
	id INT NOT NULL PRIMARY KEY,
	name VARCHAR(30) DEFAULT NULL,
	tid INT NOT NULL
);

INSERT INTO `student` (id, name, tid) VALUES(1, 's1', 1);
INSERT INTO `student` (id, name, tid) VALUES(2, 's2', 1);
INSERT INTO `student` (id, name, tid) VALUES(3, 's3', 1);

CREATE TABLE `teacher`(
	id INT NOT NULL PRIMARY KEY,
	name VARCHAR(30) DEFAULT NULL,
);

INSERT INTO `teacher` (id, name) VALUES(1, 't1');

实体类

@Data
public class Student {
    private int id;
    private String name;
//    private Teacher teacher;  // 这种方式比较好实现
    private String tname;
}

@Data
public class Teacher {
    private int id;
    private String name;
}
  • 按照查询嵌套处理

    StudentMapper.xml

<select id="getStudentById" parameterType="int" resultMap="StudentMap">
  SELECT * FROM mybatis.student WHERE id=#{id};
</select>

<resultMap id="StudentMap" type="student">
  <result property="id" column="id"/>
  <result property="name" column="name"/>
  <association property="tname" column="tid" javaType="string"
               select="com.yaohl0911.dao.TeacherMapper.getTeacherNameById"/>
</resultMap>

因为分两层查询,所以需要TeacherMapper

TeacherMapper.xml

<select id="getTeacherNameById" parameterType="int" resultType="string">
	select name from mybatis.teacher where id=#{id}
</select>
  • 按照结果嵌套处理

    因使用了sql的关联查询能力,不再需要单独写TeacherMapper

<select id="getStudentById2" parameterType="int" resultMap="StudentMap2">
  SELECT
  	s.id as sid,
  	s.name as sname,
  	t.name as tname
  FROM
  	mybatis.student s
  	left join mybatis.teacher t on s.tid = t.id
  WHERE
  	s.id=#{id};
</select>
<resultMap id="StudentMap2" type="student">
  <result property="id" column="sid"/>
  <result property="name" column="sname"/>
  <association property="tname" javaType="string">
    <result property="name" column="tname"/>
  </association>
</resultMap>

一对多查询

DB内容与多对一查询完全一致,实体类有差异

@Data
public class Student {
    private int id;
    private String name;
}

@Data
public class Teacher {
    private int id;
    private String name;
    private List<String> students; //这里的list如果是Student的话很容易实现
}

TeacherMapper.xml实现

<select id="getTeacherById" parameterType="int" resultMap="TeacherMap">
  SELECT
  	t.id as tid,
  	t.name as tname,
  	s.name as sname
  FROM
  	mybatis.student s
  	left join mybatis.teacher t on s.tid = t.id
  WHERE
  	t.id=#{id};
</select>

<resultMap id="TeacherMap" type="com.yaohl0911.pojo.Teacher">
  <result property="id" column="tid"/>
  <result property="name" column="tname"/>
  <!-- 注意:property="students"在idea中会被标红,这样是没问题的,不要被误导,它就是Teacher实体类里的第三个字段 -->
  <!-- ofType就是这个字段的类型,result就是要取出的内容 -->
  <collection property="students" ofType="string">
    <result property="name" column="sname"/>
  </collection>
</resultMap>

返回结果:

Teacher(id=1, name=t1, students=[s1, s2, s3])

分页的实现

作用:减少数据的处理量

使用SQL的limite实现分页

SELECT * FROM user limite startIndex, pageSize;

使用Mybatis实现分页

使用前面学的map实现:

<select id="getUserList" resultType="user">
    select * from mybatis.users limit #{startInde}, #{pageSize};
</select>

使用RowBounds实现分页

不推荐使用

sql内联查询

About

学习Mybatis过程的记录

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages