【Mybatis】笔记(一)

【Mybatis】笔记

一、Mybatis简介

1.1、Mybatis

  1. MyBatis是一款优秀的持久层框架
  2. MyBatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.6</version>
</dependency>

1.2、持久化

持久化就是将程序的数据在持久状态和瞬时状态转化的过程

为什么需要需要持久化?
1、有一些对象,不能让他丢掉。
2、内存太贵了

1.3、持久层

Dao层,Service层,Controller层…
完成持久化工作的代码块
层界限十分明显。

2、一个mybatis程序

2.1、搭建环境

2.1.1、创建数据库

/*
 Navicat Premium Data Transfer

 Source Server         : localhost_3306
 Source Server Type    : MySQL
 Source Server Version : 80018
 Source Host           : localhost:3306
 Source Schema         : mybatis

 Target Server Type    : MySQL
 Target Server Version : 80018
 File Encoding         : 65001

 Date: 01/01/2022 22:30:57
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` int(20) NOT NULL,
  `name` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `pwd` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, '张三', '123456');
INSERT INTO `user` VALUES (2, '李四', '123456');
INSERT INTO `user` VALUES (3, '王五', '123456');

SET FOREIGN_KEY_CHECKS = 1;

2.1.2、 新建项目导入依赖

<!--导入依赖-->
    <dependencies>
        <!--mysqL驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.21</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.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

2.2、创建模块

2.2.1、编写mybatis的核心配置文件

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?&amp;useSSL=false&amp;serverTimezone=UTC"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="com/demo01/dao/UserMapper.xml" />
    </mappers>

</configuration>

2.2.2、编写mybatis工具类

mybatisutils

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

//sqLsessionFactory
public class mybatisutils {
    public  static SqlSessionFactory sqlSessionFactory;
    static{
        //使用Mybatis第一步获取SqlSessionFactory对象
        try {
            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(){
        SqlSession sqlSession=sqlSessionFactory.openSession();
        return  sqlSession;
    }
}

2.3、编写代码

实体类 User

package com.demo01.pojo;

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

Dao接口 UserDao

package com.demo01.dao;
import com.demo01.pojo.User;
import java.util.List;

public interface UserDao {
    List<User> getUserList();
}

接口实现类 UserMapper.xml

<?xm1 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.demo01.dao.UserDao">
    <select id="getUserList" resultType="com.demo01.pojo.User">
        select * from mybatis.user;
    </select>
</mapper>

2.4、测试

test

package com.demo01.dao;
import com.demo01.pojo.User;
import com.demo01.utils.mybatisutils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;

public class UserDaoTest {
    @Test
    public void  test(){
        //第一步:获得SqLsession对象
        SqlSession sqlsession = mybatisutils.getSqlSession();
        //执行sql
        UserDao userDao=sqlsession.getMapper(UserDao.class);
        List<User> userList = userDao.getUserList();
        for (User user : userList) {
            System.out.println(user.getId());
        }
        //关闭SqLsession
        sqlsession.close();
	}
}

在junit里测试时 正常是不会扫描到src里的文件 添加下面代码进行全局扫描

<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、增删查改

3.1、属性

3.1.1、参数

  1. namespace中的包名要和Dao/mapper接口的包名一致!
  2. id 就是对应的namespace中的方法名
  3. resultType: Sql语句执行的返回值!
  4. parameterType :参数类型!

3.1.2、select

  1. 编写接口
    //根据ID查询用户
    User getUserById(int id);
  1. 编写mapper中的sql语句
    <select id="getUserById" parameterType="int" resultType="com.demo01.pojo.User">
        select * from mybatis.user where id = #{id}
    </select>
  1. 测试类
    public void getUserById(){
        SqlSession sqlsession = mybatisutils.getSqlSession();
        UserDao mapper = sqlsession.getMapper(UserDao.class);
        User user = mapper.getUserById(1);
        System.out.println(user.getName());
        sqlsession.close();
    }

3.1.3、insert

  1. 编写接口
    //插入User
    int addUser(User user);
  1. 编写mapper中的sql语句
  <insert id="addUser" parameterType="com.demo01.pojo.User">
        insert into mybatis.user (id,name,pwd) values (#{id},#{name},#{pwd});
   </insert>
  1. 测试类
 public void addUser(){
        SqlSession sqlsession = mybatisutils.getSqlSession();
        UserDao mapper = sqlsession.getMapper(UserDao.class);
        int res = mapper.addUser(new User(4,"哈哈","123333"));
        if (res>0){
            System.out.println("插入成功!");
        }
        //提交事务
        sqlsession.commit();
        sqlsession.close();
    }

3.1.4、update

  1. 编写接口
  //修改User
    int updateUser(User user);
  1. 编写mapper中的sql语句
 <update id="updateUser" parameterType="com.demo01.pojo.User">
        update mybatis.user
        set  name=#{name},pwd=#{pwd}
        where id=#{id};
    </update>
  1. 测试类
 public void updateUser(){
        SqlSession sqlsession = mybatisutils.getSqlSession();
        UserDao mapper = sqlsession.getMapper(UserDao.class);
        int res =mapper.updateUser(new User(4,"嘿嘿","123333"));
        if (res>0){
            System.out.println("修改成功!");
        }
        //提交事务
        sqlsession.commit();
        sqlsession.close();
    }

3.1.5、delete

  1. 编写接口
    //删除User
    int delUser(int id);
  1. 编写mapper中的sql语句
    <delete id="delUser" parameterType="int">
        delete
        from mybatis.user
        where id=#{id}
    </delete>
  1. 测试类
public void delUser(){
        SqlSession sqlsession = mybatisutils.getSqlSession();
        UserDao mapper = sqlsession.getMapper(UserDao.class);
        int res= mapper.delUser(4);
        if (res>0){
            System.out.println("删除成功!");
        }
        //提交事务
        sqlsession.commit();
        sqlsession.close();
    }

3.1.6、注意点

增删改需要提交事务sqlsession.commit();

3.2、Map类型传递

假设,我们的实体类,或者数据库中的表,字段或者参数过多,我们应当考虑使用Map

 int adduser2 (Map<String,Object> map);

使用map不需要和类型里的参数对应,需要与Map的key对应即可

<insert id="addUser2" parameterType="map">
    insert into mybatis.user (id,name,pwd) values (#{userId},#{userName},#{userPassword});
</insert>

3.3、模糊查询

List<User> getUserLike();

4、配置解析

4.1、配置属性

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

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

4.2、环境配置(environments)

MyBatis可以配置成适应多种环境
不过要记住:尽管可以配置多个环境,但每个SqlSessionFactory实例只能选择一种环境
Mybatis默认的事务管理器就是JDBC,连接池:POOLED

4.3、属性(properties)

我们可以通过properties属性来实现引用配置文件

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?&useSSL=false&serverTimezone=UTC
username=root
password=root
  • 可以直接引入外部文件
  • 可以在其中增加一些属性配置
  • 如果两个文件有同一个字段,优先使用外部配置文件的!
<properties resource="db.properties">
	<property name="username" value="root"/>
	<property name="pwd" value="root"/>
</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>

4.4、类型别名(typeAliases)

类型别名是为Java类型设置一个短的名字。它只和XML配置有关
存在的意义仅在于用来减少类完全限定名的冗余.

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

也可以指定一个包名,MyBatis 会在包名下面搜索需要的Java Bean,比如:
扫描实体类的包,它的默认别名就为这个类的类名,首字母小写

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

<select id="getUserList" resultType="user">

不想使用扫包默认的别名亦可以使用注解别名

@Alias("User")

4.5、设置(settings)

这是MyBatis 中极为重要的调整设置,它们会改变MyBatis 的运行时行为。下表描述了设置中各项的意图、默认值等。
【Mybatis】笔记(一)
【Mybatis】笔记(一)

4.6、生命周期与作用域

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


SqlSessionFactoryBuilder:

  • 一旦创建了SqlSessionFactory,就不再需要它了
  • 局部变量

SqlSessionFactory:

  • 说白了就是可以想象为︰数据库连接池
  • SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例
  • 因此SqlSessionFactory的最佳作用域是应用作用域。
  • 最简单的就是使用单例模式或者静态单例模式。

SqlSession:

  • 连接到连接池的一个请求!
  • SqlSession的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。
  • 用完之后需要赶紧关闭,否则资源被占用!

5、结果集映射(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 = #{fid}
</select>
  1. resultMap 元素是MyBatis中最重要最强大的元素
  2. ResultMap的设计思想是,对于简单的语句根本不需要配置显式的结果映射,而对于复杂一点的语句只需要描述它们的关系就行了。

[Mybatis】笔记(二)

点此跳转

上一篇:python 多进程 multiprocessing模块


下一篇:Mybatis-缓存解析