Mybatis总结

Posted qiu-m

tags:

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

简介

Mybatis 官网:

https://mybatis.org/mybatis-3/zh/getting-started.html

环境配置

  1. 新建一个普通的maven项目
  2. 删除项目的src目录
  3. 导入maven依赖
<!--导入依赖-->
<dependencies>
    <!--mysql驱动-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.47</version>
    </dependency>
    <!--mybatis 依赖-->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.2</version>
    </dependency>
    <!--junit 测试依赖-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    <!--lombok 依赖-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.10</version>
	</dependency>
</dependencies>

解决Maven resources资源 过滤问题

<!--在build中配置resources,来防止我们资源导出失败的问题-->
<build>
    <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>

建立模块

1、上面建立的普通Maven项目为父工程,后面都通过建立Module模块来当子工程

2、建立一个Module项目(普通maven项目)

3、在resources资源文件夹下创建配置文件 db.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8
username=root
password=123456

4、在resources资源文件夹下创建 mybatis-config.xml 文件,编写mybatis的核心配置文件

<?xml version="1.0" encoding="UTF8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--configuration核心配置文件-->
<configuration>
    <!--引入配置文件-->
    <properties resource="db.properties"/>
    <!--设置-->
    <settings>
        <!--日志设置-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
        <!--开启驼峰命名自动映射-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    <!--实体类别名-->
    <typeAliases>
        <package name="com.qiu.pojo"/>
    </typeAliases>
    <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/qiu/dao/UserMapper.xml" />
    </mappers>
</configuration>
  • 编写mybatis工具类
package com.qiu.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 MybatisUtils {
    private static SqlSessionFactory sqlSessionFactory;
    static{
        try {
            //使用Mybatis第一步:获取sqlSessionFactory对象
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    //既然有了 SqlSessionFactory,顾名思义,我们就可以从中获得 SqlSession 的实例了。
    // SqlSession 完全包含了面向数据库执行 SQL 命令所需的所有方法。
    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
    }
}

编写业务代码

创建实体类

package com.qiu.pojo;

public class User {
    private int id;
    private String name;
    private String pwd;

    public User() {
    }
    
    public User(int id, String name, String pwd) {
        this.id = id;
        this.name = name;
        this.pwd = pwd;
    }
    
    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name=‘" + name + ‘‘‘ +
                ", pwd=‘" + pwd + ‘‘‘ +
                ‘}‘;
    }
}

编写Dao层接口

public interface UserDao {
    
}

编写UserMapper.xml配置文件

接口实现类由原来的UserDaoImpl转变为一个 Mapper配置文件.

<?xml version="1.0" encoding="UTF8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace=绑定一个对应的Dao/Mapper接口-->
<mapper namespace="com.qiu.dao.UserDao">
    <!--后面的Mapper配置文件都放到这里-->
    <!--eg:select、insert、update标签等-->
</mapper>
<!-- namespace中的包名要和 Dao/mapper 接口的包名一致!-->

编写测试类

import org.junit.Test;
public class UserDaoTest {

}

CURD

下面的步骤顺序为:接口、Mapper配置文件、测试类

查询全部用户

//查询全部用户
List<User> getUserList();
<!--select查询语句-->
<select id="getUserList" resultType="user">
    select * from mybatis.user
</select>

解释:
 id : 就是对应的namespace中的方法名;
 resultType:Sql语句执行的返回值!(如果为集合,则写集合中的泛型)
 parameterType : 参数类型!
@Test
public void getUserList(){
    //第一步,获得SqlSession对象
    SqlSession sqlSession = MybatisUtils.getSqlSession();

    //方式一:getMapper
    UserMapper userDao = sqlSession.getMapper(UserMapper.class);
    List<User> userList = userDao.getUserList();

    for (User user:userList) {
        System.out.println(user);
    }

    //关闭SqlSession
    sqlSession.close();
}

根据ID查询用户

//根据ID查询用户
User getUserById(int id);
<!--根据ID查询用户-->
<select id="getUserById" parameterType="int" resultType="com.qiu.pojo.User">
    select * from mybatis.user where id = #{id}
</select>
@Test
public void getUserById(){
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    User user = mapper.getUserById(1);
    System.out.println(user);
    sqlSession.close();
}

插入用户

//插入用户
int addUser(User user);
<!--对象中的属性,可以直接取出来-->
<insert id="addUser" parameterType="user">
    insert into mybatis.user (id, name, pwd) values (#{id},#{name},#{pwd});
</insert>
@Test
public void addUser(){
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    int ok = mapper.addUser(new User(5, "李六", "123456"));
    if(ok>0){
        System.out.println("插入成功!");
    }
    sqlSession.commit();	//提交事务
    sqlSession.close();
}

修改用户

//修改用户
int updateUser(User user);
<update id="updateUser" parameterType="user">
    update mybatis.user set name=#{name},pwd=#{pwd} where id=#{id};
</update>
@Test
public void updateUser(){
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    int ok = mapper.updateUser(new User(4, "赵六", "123456"));
    if(ok>0){
        System.out.println("修改成功");
    }
    sqlSession.commit();
    sqlSession.close();
}

删除用户

//删除用户
int deleteUser(int id);
<!--删除用户-->
<delete id="deleteUser" parameterType="int">
    delete from mybatis.user where id=#{id}
</delete>
@Test
public void deleteUser(){
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    int ok = mapper.deleteUser(4);
    if(ok>0){
        System.out.println("删除成功!");
    }
    sqlSession.commit();
    sqlSession.close();
}

分页

//分页
List<User> getUserByLimit(Map<String,Integer> map);
<select id="getUserByLimit" parameterType="map" resultType="user">
    select * from mybatis.user limit #{startIndex},#{pageSize}
</select>
@Test
public void getUserByLimit(){
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    HashMap<String, Integer> map = new HashMap<String, Integer>();
    map.put("startIndex",0);
    map.put("pageSize",3);
    List<User> userList = mapper.getUserByLimit(map);
    for (User user : userList) {
        System.out.println(user);
    }
    sqlSession.close();
}

基于RowBounds分页

//RowBounds分页
List<User> getUserByRowBounds();
<!--RowBounds分页-->
<select id="getUserByRowBounds" resultType="user">
    select * from mybatis.user
</select>
@Test
public void getUserByRowBounds(){
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    RowBounds rowBounds = new RowBounds(0, 3);
    List<User> userList = sqlSession.selectList(
        "com.qiu.dao.UserMapper.getUserByRowBounds", null, rowBounds);
    for (User user : userList) {
        System.out.println(user);
    }
    sqlSession.close();
}

模糊查询

模糊查询怎么写?

  1. Java代码执行的时候,传递通配符 % %

    List<User> userList = mapper.getUserLike("%李%");
    
  2. 在sql拼接中使用通配符!

    select * from mybatis.user where name like "%"#{value}"%"
    

注意点:

  • 增删改需要提交事务!

  • 可以在工具类创建的时候实现自动提交事务!

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

动态SQL

什么是动态SQL:动态SQL就是指根据不同的条件生成不同的SQL语句

if
choose (when, otherwise)
trim (where, set)
foreach

搭建环境

CREATE TABLE `blog` (
  `id` varchar(50) NOT NULL COMMENT ‘博客id‘,
  `title` varchar(100) NOT NULL COMMENT ‘博客标题‘,
  `author` varchar(30) NOT NULL COMMENT ‘博客作者‘,
  `create_time` datetime NOT NULL COMMENT ‘创建时间‘,
  `views` int(30) NOT NULL COMMENT ‘浏览量‘
) ENGINE=InnoDB DEFAULT CHARSET=utf8

创建实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Blog {
    private int id;
    private String title;
    private String author;
    private Date createTime;
    private int views;
}

查询数据

//查询数据
List<Blog> queryBlogIF(Map map);
<sql id="if-blog">
    <if test="title != null">
        and title = #{title}
    </if>
    <if test="author != null">
        and author = #{author}
    </if>
    <if test="views != null">
        and views &gt; #{views}
    </if>
</sql>

<select id="queryBlogIF" parameterType="map" resultType="Blog">
    select * from mybatis.blog
    <where>
        <include refid="if-blog"/>	<!--引入上面定义的sql-->
        <if test="createTime != null">
            and create_time &lt; #{createTime}
        </if>
    </where>
</select>
@Test
public void queryBlogIF(){
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
    Map map= new HashMap();
    //map.put("views",5000);
    List<Blog> blogs = mapper.queryBlogIF(map);
    for (Blog blog : blogs) {
        System.out.println(blog);
    }
    sqlSession.close();
}

指定更新

//指定更新
int updateBlog(Map map);
<update id="updateBlog" parameterType="map">
    update mybatis.blog
    <set>
        <if test="title != null">
            title = #{title},
        </if>
        <if test="author != null">
            author = #{author}
        </if>
    </set>
    where id = #{id}
</update>
@Test
public void updateBlog(){
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);

    HashMap map = new HashMap();
    map.put("title","我要学习框架");
    map.put("id",1);
    int ok = mapper.updateBlog(map);
    if(ok>0){
        System.out.println("更新成功!");
    }
    sqlSession.close();
}

指定删除

//指定删除
int delBlog(Map map);
<delete id="delBlog" parameterType="map">
    delete from mybatis.blog
    <where>
        <include refid="if-blog"/>
        <if test="createTime != null">
            and create_time &gt; #{createTime}
        </if>
    </where>
</delete>
<!--  &lt; 小于号   &gt; 大于号-->
@Test
public void delBlog(){
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
    HashMap map = new HashMap();
    map.put("createTime","2020-06-05 16:49:00");
    int ok = mapper.delBlog(map);
    queryBlog();
    sqlSession.close();
}

配置解析

核心配置文件

mybatis-config.xml

MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。

configuration(配置)
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)

类型别名(typeAliases)

类型别名是为 Java 类型设置一个短的名字。

存在的意义仅在于用来减少类完全限定名的冗余。

<!--可以给实体类起别名-->
<typeAliases>
    <typeAlias type="com.kuang.pojo.User" alias="User"/>
</typeAliases>

也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,比如:

扫描实体类的包,它的默认别名就为这个类的 类名,首字母小写!

<!--可以给实体类起别名-->
<typeAliases>
    <package name="com.kuang.pojo"/>
</typeAliases>

在实体类比较少的时候,使用第一种方式。

如果实体类十分多,建议使用第二种。

第一种可以DIY别名,第二种则不行,如果非要改,需要在实体上增加注解

@Alias("user")
public class User {}

结果集映射(resultMap)

作用:解决属性名和字段名不一致的问题

id   name   pwd
id   name   password
<!--结果集映射-->
<resultMap id="UserMap" type="User">
    <!--column数据库中的字段,property实体类中的属性-->
    <result column="id" property="id"/>
    <result column="name" property="name"/>
    <result column="pwd" property="password"/>
</resultMap>

<select id="getUserById" resultMap="UserMap">
    select * from mybatis.user where id = #{id}
</select>

映射器(mappers)

MapperRegistry:注册绑定我们的Mapper文件;

方式一: 【推荐使用】

<!--每一个Mapper.XML都需要在Mybatis核心配置文件中注册!-->
<mappers>
    <mapper resource="com/kuang/dao/UserMapper.xml"/>
</mappers>

方式二:使用class文件绑定注册

<!--每一个Mapper.XML都需要在Mybatis核心配置文件中注册!-->
<mappers>
    <mapper class="com.kuang.dao.UserMapper"/>
</mappers>

注意点:

  • 接口和他的Mapper配置文件必须同名!
  • 接口和他的Mapper配置文件必须在同一个包下!

方式三:使用扫描包进行注入绑定

<!--每一个Mapper.XML都需要在Mybatis核心配置文件中注册!-->
<mappers>
    <package name="com.kuang.dao"/>
</mappers>

注意点:

  • 接口和他的Mapper配置文件必须同名!
  • 接口和他的Mapper配置文件必须在同一个包下!

日志(log4j)

首先导入log4j的包

<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

在resources资源文件夹下创建 log4j.properties 配置文件

#将等级为DEBUG的日志信息输出到console和file这两个目的地,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=[%c]-%m%n

#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/kuang.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%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

配置log4j为日志的实现

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

常见报错情况

第一种:1 字节的 UTF-8 序列的字节 1 无效。

技术图片

原因:

? 在配置文件中引入了<?xml version="1.0" encoding="UTF-8"?>, 在配置文件可能包含有中文注释,导致在编译后中文注释在配置文件乱码抛异常。

解决方案1:

在项目依赖配置文件pom.xml上加入构建项目编码属性

<properties>
	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

解决方案2:

把UTF-8改为UTF8

注意点:

org.apache.ibatis.binding.BindingException: Type interface com.kuang.dao.UserDao is not known to the MapperRegistry.

检查核心配置文件中是否注册 mappers

本篇总结参考 B站狂神说Javahttps://space.bilibili.com/95256449

以上是关于Mybatis总结的主要内容,如果未能解决你的问题,请参考以下文章

Mybatis——Dao层实现映射文件深入核心配置文件深入

markdown [mybatis参考]关于mybatis #mybatis的一些片段

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

python常用代码片段总结

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

BootStrap有用代码片段(持续总结)