mybatis学习笔记

Mybatis

环境:

  • JDk1.8
  • Mysql 5.7
  • maven 3.6.1
  • IDEA

回顾 :

  • JDBC
  • MYsql
  • Java基础
  • Junit 测试

框架是有配置文件的, 最好的学习方式是看官方文档 ;

1 简介


1.1 什么是Mybatis

  • Mybatis是一款优秀的持久层框架

如何获得Mybatis

1.2 持久化

数据持久化 :

  • 持久化就是将程序的数据在持久状态和瞬时状态转化的过程
  • 内存中的数据 : 断电即数据丢失
  • 数据库(Jdbc) / io文件持久化

为什么需要持久化?

  • 有一些对象不能丢失
  • 内存太贵

1.3 持久层

之前接触过 Dao层 / Service层 / Controller层 ...

什么是持久层?

  • 完成持久化工作的代码块
  • 层是界限十分明显的

1.4 为什么需要Mybatis?

  • 帮助程序员将数据存入数据库
  • 方便
  • 传统的JDBC代码太复杂了 , 为了简化代码的框架
  • 自动化

最重要的一点 :

  • 使用的人多

2 第一个mybatis程序

思路 : 搭建环境-> 导入Mybatis-> 编写代码-> 测试

2.1 创建表

CREATE DATABASE IF NOT EXISTS `mybatis`;

USE `mybatis`;

CREATE TABLE IF NOT EXISTS `user`(
	`id` INT(20) NOT NULL PRIMARY KEY,
	`name` VARCHAR(30) DEFAULT NULL,
	`pwd` VARCHAR(30) DEFAULT NULL
)ENGINE=INNODB CHARSET=utf8;

INSERT INTO `user`(`id`, `name`, `pwd`)VALUES
(1, 'karl', '123456'),
(2, 'xiao', '123434'),
(3, 'gels', '123321');

2.2新建一个maven项目

mybatis-01/ pom.xml

<!--父工程-->
    <dependencies>
        <!--mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.23</version>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>
        <!--junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

2.3 创建模块

创建mabatis配置文件

src/ main/ recource/ 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.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=Asia/Shanghai&amp;useUnicode=true&amp;characterEncoding=utf-8&amp;useSSL=true"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="org/mybatis/example/BlogMapper.xml"/>
    </mappers>
</configuration>

创建工具类

package com.karl.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;

/**
 * @author admin
 * @version 1.0.0
 * @ClassName MybatisUtils.java
 * @Description 工具类 sqlSessionFactory -> sqlSession
 * @createTime 2021年03月19日 13:18:00
 */
public class MybatisUtils {

    private static SqlSessionFactory sqlSessionFactory = null;

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

    }
    //sqlSession完全包含了面向数据库执行SQL命令需要的所有方法
    public static SqlSession getSqlSession(){ 
        return sqlSessionFactory.openSession();
    }

}

2.3 编写代码

  • 实体类

    package com.karl.pojo;
    
    /**
     * @author admin
     * @version 1.0.0
     * @ClassName User.java
     * @Description 实体类
     * @createTime 2021年03月21日 13:21:00
     */
    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 + '\'' +
                    '}';
        }
    
    }
    
  • mapper接口

    package com.karl.mapper;
    
    import com.karl.pojo.User;
    
    import java.util.List;
    
    /**
     * @author admin
     * @version 1.0.0
     * @ClassName UserMapper.java
     * @Description Dao接口
     * @createTime 2021年03月21日 13:27:00
     */
    public interface UserMapper {
        List<User> getUserList();
    }
    
  • 接口实现类由原来的DaoImpl转变为一个Maper配置文件

    <?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.karl.mapper.UserMapper">
        <select id="getUserList" resultType="com.karl.pojo.User">
        select * from user
      </select>
    </mapper>
    

2.4 测试

注意 : BindingException: Type interface com.karl.dao.UserDao is not known to the MapperRegistry.

  • junit测试

    官方推荐的格式确保 SqlSession 关闭的标准模式:

    try (SqlSession session = sqlSessionFactory.openSession()) {
      // 你的应用逻辑代码
    }
    
    package com.karl.mapper;
    
    import com.karl.pojo.User;
    import com.karl.utils.MybatisUtils;
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    
    import java.util.List;
    
    /**
     * @author admin
     * @version 1.0.0
     * @ClassName UserMapperTest.java
     * @Description 测试sql
     * @createTime 2021年03月21日 13:59:00
     */
    public class UserMapperTest {
        @Test
        public void test(){
            try (SqlSession sqlSession = MybatisUtils.getSqlSession()) {
                //执行
                UserMapper mapper = sqlSession.getMapper(UserMapper.class);
                List<User> userList = mapper.getUserList();
                for (User user : userList) {
                    System.out.println(user);
                }
            }
        }
    }
    
  • 在mybatis-config中配置mapper

        <!--每一个Mapper.xml都需要在Mybatis-config核心配置文件中注册-->
        <mappers>
            <mapper resource="com/karl/mapper/UserMapper.xml"/>
        </mappers>
    
  • maven中配置文件存放的问题

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

3 CRUD

namespace中的包名要和mapper接口的包名一致

  • id : 是namespace中的方法名
  • resultType : Sql语句的返回值
  • parameterType : 参数类型

1 select

选择 , 查询语句

接口 UserMapper.java

    //按id查找用户
    User getUserByID(int id);

UserMapper.xml

    <select id="getUserByID" parameterType="int" resultType="com.karl.pojo.User">
        select * from mybatis.user where id = #{id}
    </select>
@Test
public void getUserByID(){
    try (SqlSession sqlSession = MybatisUtils.getSqlSession()){
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User userByID = mapper.getUserByID(1);
        System.out.println(userByID);

    }
}

2 insert(增删改需要提交事务)

插入语句

接口 UserMapper.java

    //添加一个用户
    int addUser(User user);

UserMapper.xml

    <!--对象中的属性可以直接拿出来-->
    <insert id="addUser" parameterType="com.karl.pojo.User">
        insert into mybatis.user (id, name, pwd) values (#{id}, #{name}, #{pwd});
    </insert>
    @Test
    public void addUser(){
        try (SqlSession sqlSession = MybatisUtils.getSqlSession()){
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            User user = new User(4, "kkk", "123432");
            mapper.addUser(user);
            sqlSession.commit();
        }
    }

3 update

    //修改用户
    int updateUser(User user);
    <update id="updateUser" parameterType="com.karl.pojo.User">
        update mybatis.user
        set name = #{name},
            pwd  = #{pwd}
        where id = #{id};
    </update>
@Test
    public void updateUser(){
        try(SqlSession sqlSession = MybatisUtils.getSqlSession()){
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            User user = new User(5, "lll", "111222");
            int result = mapper.updateUser(user);
            sqlSession.commit();
            if (result > 0){
                System.out.println("修改成功");
            }
        }
    }

4 delete

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

5 常见错误

image-20210329125321701

6 万能的map

在参数或字段过多的时候 , 可以考虑使用map

弹幕提示调试很麻烦

    //使用Map添加一个用户
    int addUser2(Map<String, Object> map);
    <!--使用map传递参数-->
    <insert id="addUser2" parameterType="map">
        insert into mybatis.user(id, name, pwd)
        values (#{userID}, #{userName}, #{password});
    </insert>
    @Test
    public void addUser2(){
        try (SqlSession sqlSession = MybatisUtils.getSqlSession()){
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            HashMap<String, Object> stringObjectHashMap = new HashMap<>();
            stringObjectHashMap.put("userID",10);
            stringObjectHashMap.put("userName","uuu");
            stringObjectHashMap.put("password","iiiii");

            mapper.addUser2(stringObjectHashMap);
            sqlSession.commit();
        }
    }

image-20210329140452017

8 模糊查询怎么写

  1. java执行代码时传递通配符

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

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

4 配置解析

配置顺序

1 核心配置文件(mybatis-config)

mybatis-config.xml名字可以随便取 , 但官方推荐用这个名字

The content of element type "configuration" must match "(properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,reflectorFactory?,plugins?,environments?,databaseIdProvider?,mappers?)".

文件中的配置需要按照此顺序

2 environments(环境配置

MyBatis 可以配置成适应多种环境,不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。

使用default="development" 切换多套环境

mybatis 默认的事务管理器是JDBC , 连接为POOLED(池)

3 属性(properties)

可以使用peoperties属性引用配置文件

编写一个配置文件db.properties

drier=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&useSSL=true
username=root
password=123456

在核心配置文件(mybatis-config.xml)中引入

<properties resource="mybatis/db.properties"></properties>
<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>
  • 可以引入外部文件

  • 也可以在

        <properties resource="mybatis/db.properties">
            <property name="" value=""/>
        </properties>
    

    中添加属性

  • 两个文件有同一个字段 , 优先使用外部属性

4 类型别名(typeAliases)

  • 可为 Java 类型设置一个缩写名字 , 意在降低冗余的全限定类名书写。

        <!--别名-->
        <typeAliases>
            <typeAlias type="com.karl.pojo.User" alias="User"/>
        </typeAliases>
    
  • 也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean , 别名默认为这个类名但首字母为小写

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

    可以使用注解自定义名字

    @Alias("author")
    public class Author {
        ...
    }
    

5 设置(settings)

image-20210402112125212

image-20210402112137183

6 其他配置

7 映射器 mapper

  • 方式一

        <mappers>
            <mapper resource="mybatis/mapper/UserMapper.xml"/>
        </mappers>
    
  • 方式二 : 使用class的文件绑定

    <mappers>
        <mapper class="com.karl.mapper.UserMapper"/>
    </mappers>
    
  • 方式三 : 使用包扫描绑定

        <mappers>
            <package name="mybatis.mapper"/>
        </mappers>
    
  • 方式二和方式三必须注意 :

    • 接口和它的Mapper配置文件必须同名 ;
    • 接口和它的Mapper配置文件必须在同一个包下 ;
    • 解决maven的资源导出问题 ;

8 生命周期和作用域

作用域和生命周期类别是至关重要的,因为错误的使用会导致非常严重的并发问题。

SqlSessionFactoryBuilder :

  • 它是用来创建SqlSessionFactory 的,
  • 一旦创建了 SqlSessionFactory,就不再需要它了。

SqlSessionFactory :

  • 可以理解为数据库连接池
  • 一旦被创建就应该在应用的运行期间一直存在
  • 使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次
  • 因此 SqlSessionFactory 的最佳作用域是应用作用域
  • 最简单的就是使用单例模式或者静态单例模式

SqlSession :

  • 连接到连接池的一个请求
  • 用完就要关闭
  • 每个线程都应该有它自己的 SqlSession 实例
  • SqlSession 的实例不是线程安全的,因此是不能被共享的
  • 所以它的最佳的作用域是请求或方法作用域

5 解决属性名和字段名不一致的问题

当类中的属性名和数据库中的方法不一致时 :

例如 :

类中的属性名为 password 而数据库中的字段是 pwd 时出现的不能读取到的问题 ;

1. 可以"起别名"

select id,name,pwd as password form mybatis.user where id = #{id};

2 . 可以使用 ResultMap 结果集映射

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

6 日志

6.1 日志工厂

在debug时 , 日志是很好的排错手段

设置名 描述 有效值 默认值
logImpl 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING 未设置

掌握 :

  • STDOUT_LOGGING
  • LOG4J

STDOUT_LOGGING

<settings>
	<setting name="logImpl" value="STDOUT_LOGGING">
</settings>
  • 设置名和值不能错

LOG4J

  1. 导入LOG4J的包

        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
    
  2. 写配置文件

    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
    
  3. LOG4J 设置为日志实现

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

简单使用

  1. 导入包

    import org.apache. log4j.Logger;
    
  2. 创建对象

    static Logger logger = Logger.getLogger(UserDaoTest.class);
    
  3. 在需要的地方调用方法

    logger.info;
    

TODO

https://www.bilibili.com/video/BV1NE411Q7Nx?p=11

https://mybatis.org/mybatis-3/zh/index.html

posted @ 2021-04-06 12:12  卡尔书院  阅读(81)  评论(0编辑  收藏  举报