疯狂的MyBatis

MyBatis

1.概述

MyBatis是一款优秀的持久化框架,支持自定义SQL,存储过程以及高级映射,MyBatis免去了几乎所有的JDBC代码,以及设置参数,获取结果集对象。MyBatis可以通过简单的XML配置或注解来配置映射关系

Hibernate框架:全自动映射ORM框架

2.为什么使用MyBatis

JDBC:

​ SQL编写在代码中,耦合度比较高

​ 实际开发中SQL会经常被更新,维护不易

Hibernate

​ 内部自动生成SQL,不方便特殊优化

​ 长难复杂的SQL,处理很不容易

​ 基于全映射的全自动框架,进行字段部分映射比较困难,并且会导致数据库性能下降

MyBatis

​ SQL和JAVA编码分离,功能划分请出,一个专注数据,一个专注业务

​ 核心SQL可以自己编写,优化比较方便

3.MyBatis环境搭建(XML解析入门)

3.1环境搭建

步骤:

​ 1.创建Maven工程,并导入相关依赖

​ 2.创建实体类

​ 3.创建dao层接口

​ 4.创建MyBatis主配置文件:SqlMapConfig.xml

​ 5.创建映射配置文件:UserDao.xml

注意事项:

1.创建directory和package的区别

​ directory:com.wdzl.dao创建的一级目录

​ package:com.wdzl.dao创建三级目录

2.MyBatis的映射配置文件所在目录层级要与对应的dao层接口目录层级相同

3.映射配置文件mapper标签namespace属性值必须是对应接口的全线定类名

4.映射配置文件select标签id属性必须与对应的方法名一致,不能随便写

5.只要遵循2,3,4的规定,我萌就不用去写接口类的实现类

  • 1.创建Maven工程,并导入相关依赖

    <?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.wdzl</groupId>
        <artifactId>HelloMybatis2</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <dependencies>
            <!-- 测试单元 -->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
                <scope>test</scope>
            </dependency>
    
            <!-- Mysql连接驱动 -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.6</version>
            </dependency>
    
            <!-- mybatis -->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.5.6</version>
            </dependency>
    
            <!-- 日志解析lo4j -->
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.17</version>
            </dependency>
        </dependencies>
    
    
    </project>
    
  • 2.创建实体类

    package com.wdzl.pojo;
    
    /**
     * 学生类
     */
    public class Student {
        private int id;
        private String username;
        private String gender;
        private String birthday;
        private String address;
    
        public Student() {
        }
    
        @Override
        public String toString() {
            return "Student{" +
                    "id=" + id +
                    ", username='" + username + '\'' +
                    ", gender='" + gender + '\'' +
                    ", birthday='" + birthday + '\'' +
                    ", address='" + address + '\'' +
                    '}';
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getGender() {
            return gender;
        }
    
        public void setGender(String gender) {
            this.gender = gender;
        }
    
        public String getBirthday() {
            return birthday;
        }
    
        public void setBirthday(String birthday) {
            this.birthday = birthday;
        }
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        public Student(int id, String username, String gender, String birthday, String address) {
            this.id = id;
            this.username = username;
            this.gender = gender;
            this.birthday = birthday;
            this.address = address;
        }
    }
    
    
  • 3.创建dao层接口

    package com.wdzl.dao;
    
    import com.wdzl.pojo.Student;
    
    import java.util.List;
    
    /**
     * 操作用户数据的接口
     */
    public interface UserDao {
        /**
         * 查询所有用户信息
         */
        List<Student> findAll();
    }
    
    
  • 4.创建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>
        <!-- 配置环境 -->
        <environments default="mysql">
            <environment id="mysql">
                <!-- 配置事务的类型 -->
                <transactionManager type="JDBC"></transactionManager>
                <!-- 配置数据源-->
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
                    <property name="username" value="root"/>
                    <property name="password" value="root"/>
                </dataSource>
            </environment>
        </environments>
    
        <mappers>
            <mapper resource="com/wdzl/dao/UserDao.xml"></mapper>
        </mappers>
    </configuration>
    
  • 5.创建映射配置文件:UserDao.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="com.wdzl.dao.UserDao"><!-- 对应dao层的全限定类名-->
        <select id="findAll" resultType="com.wdzl.pojo.Student">
            select*from student;
        </select>
    </mapper>
    
3.2入门测试案例

步骤:

​ 1.读取配置文件

​ 2.创建SqlSessionFactory对象—>通过SqlSessionFactoryBuilder对象获取

​ 3.使用工厂对象生产SqlSession对象

​ 4.使用SqlSession对象获取接口代理对象

​ 5.使用代理对象调用方法

​ 6.释放资源

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gTXoaik7-1616670375501)(D:\图片\8A46D97A-1AEE-47da-BBAA-945612CF9570.png)]

package com.wdzl.dao;

import com.wdzl.pojo.Student;
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 org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

/**
 * UserDao测试类
 *
 * MyBatis入门案列测试实现步骤
 *      1.读取配置文件
 *      2.创建SqlSessionFactory工厂
 *      3.用工厂生产SqlSession对象
 *      4.使用SqlSession对象创建dao层代理对象
 *      5.使用代理对象执行方法
 *      6.释放资源
 */
public class UserDaoTest {
    @Test
    public void findAllTest() throws IOException {
        //1.读取配置文件
        InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.创建SqlSessionFactory工厂
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory =builder.build(resourceAsStream);
        //3.用工厂生产SqlSession对象
        SqlSession session = factory.openSession();
        //4.使用SqlSession对象创建dao层代理对象
        UserDao userDao = session.getMapper(UserDao.class);
        //5.使用代理对象执行方法
        List<Student> students = userDao.findAll();
        //遍历
        for (Student student:students){
            System.out.println(student);
        }
        //6.释放资源
        session.close();
        resourceAsStream.close();

    }

}

4.MyBatis 注解入门

1.先新建一个Maven工程,将上一个工程的内容都复制到该工程中

2.映射配置文件就不需要了我们可以将它删除掉,并在相应的接
口方法上写上注解即可

package com.wdzl.dao;

import com.wdzl.pojo.Student;
import org.apache.ibatis.annotations.Select;

import java.util.List;

/**
 * 操作用户数据的接口
 */
public interface UserDao {
    /**
     * 查询所有用户信息
     */
    @Select("select*from student")
    List<Student> findAll();
}

3.修改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>
    <!-- 配置环境 -->
    <environments default="mysql">
        <environment id="mysql">
            <!-- 配置事务的类型 -->
            <transactionManager type="JDBC"></transactionManager>
            <!-- 配置数据源-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper class="com.wdzl.dao.UserDao"/>
    </mappers>
</configuration>

5.自定义MyBatis

5.1分析

MyBatis在使用代理的方式实现增删改查时都做了什么

  • 创建代理对象

  • 在代理对象中创建方法

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oiCnzmhL-1616670375504)(D:\图片\QQ截图20210325153443.png)]

    由图可知,执行代码需要两组信息

    ​ 1.连接信息

    ​ 2.映射信息

    ​ 执行SQL语句

    ​ 封装结果的实体类全限定类名

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ke7OWg7X-1616670375511)(D:\图片\QQ截图20210325154024.png)]

5.2自定义MyBatis

1.新建Module

2.将第一个入门案例整体拷贝到改Module中,并在pom.xml中删除Mybatis的依赖信息

3.Resources 类

package com.wdzl.io;

import java.io.InputStream;

/**
 *
 */
public class Resources {
    public static InputStream getResourceAsStream(String filePath){
        return Resources.class.getClassLoader().getResourceAsStream(filePath);
    }
}

4.创建SqlSessionFactoryBuilder类

package com.wdzl.SqlSession;

import com.wdzl.SqlSession.imp.SqlSessionFactoryImpl;
import com.wdzl.pojo.Configuration;
import com.wdzl.utils.XMLConfigBuilder;

import java.io.InputStream;

/**
 * 创建工厂
 */
public class SqlSessionFactoryBuilder {
    public SqlSessionFactory build(InputStream inputStream){
        Configuration cfg= XMLConfigBuilder.loadConfiguration(inputStream);

        return new SqlSessionFactoryImpl(cfg);
    }
}

5.创建SqlSessionFactory接口

package com.wdzl.SqlSession;

public interface SqlSessionFactory {
    SqlSession openSession();
}

6.创建SqlSession

package com.wdzl.SqlSession;

/**
 * 自定义MyBatis框架核心接口
 */
public interface SqlSession {
    /**
     * 根据接口创建代理对象
     * @param daoInterfaceClass
     * @param <T>
     * @return
     */
    <T> T getMapper(Class<T> daoInterfaceClass);

    /**
     * 释放资源
     *
     */
    void close();

}

7.导入XML解析工具类:XMLConfigBuilder 和 相关依赖

<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.1.6</version>
</dependency>

8.创建Configration类

package com.wdzl.pojo;

import java.util.HashMap;
import java.util.Map;

public class Configuration {
    private String driver;
    private String url;
    private String username;
    private String password;
    private Map<String,Mapper> mappers=new HashMap<>();

    public Map<String, Mapper> getMappers() {
        return mappers;
    }

    public void setMappers(Map<String, Mapper> mappers) {
        this.mappers.putAll(mappers);
    }

    public String getDriver() {
        return driver;
    }

    public void setDriver(String driver) {
        this.driver = driver;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

9.创建Mapper对象

package com.wdzl.pojo;

/**
 * 用于封装执行的sql语句和结果类型的全限定类型的类
 */
public class Mapper {
    private String queryString;//sql语句
    private String resultType;//实体类的全限定类名

    public String getQueryString() {
        return queryString;
    }

    public void setQueryString(String queryString) {
        this.queryString = queryString;
    }

    public String getResultType() {
        return resultType;
    }

    public void setResultType(String resultType) {
        this.resultType = resultType;
    }
}

10.在 Configuration 中添加成员变量: Mappers

private Map<String,Mapper> mappers=new HashMap<>();

11.回到 SqlSessionFactoryBuilder 编写 build 方法

  return new SqlSessionFactoryImpl(cfg);
  1. 新建 SqlSessionFactoryImpl 实现类,实现 SqlSessionFactory 接口

    package com.wdzl.SqlSession.imp;
    
    import com.wdzl.SqlSession.SqlSession;
    import com.wdzl.SqlSession.SqlSessionFactory;
    import com.wdzl.pojo.Configuration;
    
    public class SqlSessionFactoryImpl implements SqlSessionFactory {
        private Configuration cfg;
    
        public SqlSessionFactoryImpl(Configuration cfg){
            this.cfg=cfg;
        }
        @Override
        public SqlSession openSession() {
            return new SqlSessionImpl(cfg);
        }
    }
    
    

13.创建 SqlSession 的实现类对象: SqlSessionImpl

package com.wdzl.SqlSession.imp;

import com.wdzl.SqlSession.SqlSession;
import com.wdzl.pojo.Configuration;
import com.wdzl.proxy.MapperProxy;
import com.wdzl.utils.DataSourceUtil;

import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.SQLException;

public class SqlSessionImpl implements SqlSession {
    private Configuration cfg;
    private Connection connection;

    public SqlSessionImpl(Configuration cfg){
        this.cfg=cfg;
        connection= DataSourceUtil.getConnection(cfg);
    }
    @Override
    public <T> T getMapper(Class<T> daoInterfaceClass) {
        return (T) Proxy.newProxyInstance(daoInterfaceClass.getClassLoader(),
                new Class[]{daoInterfaceClass},
                new MapperProxy(cfg.getMappers(),connection));
    }

    @Override
    public void close() {
        try {
            connection.close();
        } catch (SQLException sqlException) {
            sqlException.printStackTrace();
        }

    }
}

  1. 使用动态代理实现getMapper()方法

       @Override
        public <T> T getMapper(Class<T> daoInterfaceClass) {
            return (T) Proxy.newProxyInstance(daoInterfaceClass.getClassLoader(),
                    new Class[]{daoInterfaceClass},
                    new MapperProxy(cfg.getMappers(),connection));
        }
    

15.创建InvocationHandler接口的实现类:MapperProxy

package com.wdzl.proxy;

import com.wdzl.pojo.Mapper;
import com.wdzl.utils.Executor;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.util.Map;

public class MapperProxy implements InvocationHandler {
    private Map<String, Mapper> mappers;
    private Connection connection;
    public MapperProxy(Map<String,Mapper> mappers,Connection connection){
        this.mappers=mappers;
        this.connection=connection;
    }

    /**
     * 用于增强findAll()方法
     * @param proxy
     * @param method
     * @param args
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //1.获取方法名
        String methodName = method.getName();
        //2.获取方法所在的全限定类名
        String className = method.getDeclaringClass().getName();
        //3.组装key
        String key=className+"."+methodName;
        //4.获取mapper对象
        Mapper mapper = mappers.get(key);
        //判断是否存在
        if (mapper==null){
            throw new IllegalAccessException("传入数据异常");
        }
        //6.执行
        return new Executor().selectList(mapper,connection);


    }
}

16.编写 DataSourceUtil

package com.wdzl.utils;


import com.wdzl.pojo.Configuration;

import java.sql.Connection;
import java.sql.DriverManager;

/**
 * @author lp
 * @version 1.0
 * 用于创建数据源的工具类
 */
public class DataSourceUtil {

    /**
     * 用于获取一个连接
     * @param cfg
     * @return
     */
    public static Connection getConnection(Configuration cfg){
        try {
            Class.forName(cfg.getDriver());
            return DriverManager.getConnection(cfg.getUrl(), cfg.getUsername(), cfg.getPassword());
        }catch(Exception e){
            throw new RuntimeException(e);
        }
    }
}

17.测试

package com.wdzl.dao;

import com.wdzl.io.Resources;
import com.wdzl.pojo.Student;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

/**
 * UserDao测试类
 *
 * MyBatis入门案列测试实现步骤
 *      1.读取配置文件
 *      2.创建SqlSessionFactory工厂
 *      3.用工厂生产SqlSession对象
 *      4.使用SqlSession对象创建dao层代理对象
 *      5.使用代理对象执行方法
 *      6.释放资源
 */
public class UserDaoTest {
    @Test
    public void findAllTest() throws IOException {
        //1.读取配置文件
        InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.创建SqlSessionFactory工厂
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory =builder.build(resourceAsStream);
        //3.用工厂生产SqlSession对象
        SqlSession session = factory.openSession();
        //4.使用SqlSession对象创建dao层代理对象
        UserDao userDao = session.getMapper(UserDao.class);
        //5.使用代理对象执行方法
        List<Student> students = userDao.findAll();
        //遍历
        for (Student student:students){
            System.out.println(student);
        }
        //6.释放资源
        session.close();
        resourceAsStream.close();

    }

}

6.MyBatis-CRUD操作

测试前准备工作

  @Before
    public void init() throws IOException {
        //1.读取配置文件
        is = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.创建SqlSessionFactory工厂
        builder = new SqlSessionFactoryBuilder();
        factory =builder.build(is);
        //3.用工厂生产SqlSession对象
         sqlSession = factory.openSession();
        //4.使用SqlSession对象创建dao层代理对象
        userDao = sqlSession.getMapper(UserDao.class);
    }

测试后释放资源

 @After
    public void destroy() throws IOException {
        sqlSession.close();
        is.close();

    }
6.1查询
1. 在UserDao中添加方法
    /**
     * 查询
     * @return
     */
    List<User> findAll();

2.在UserDao.xml中配置该方法

 <select id="findAll" resultMap="userMap">
      select*from user;

  </select>

3.编写测试类

    @Test
    public void findAllTest() throws IOException {


        //5.使用代理对象执行方法
        List<User> users = userDao.findAll();
        //遍历
        for (User user:users){
            System.out.println(user);
        }


    }

6.2添加

1.在UserDao中添加方法

/**
     * 添加用户
     * @param user
     */
    void addUser(User user);

2.在UserDao.xml中配置该方法

<!--添加用户-->
  <insert id="addUser" parameterType="com.wdzl.pojo.User">

     insert into user (username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address});
    </insert>

3.编写测试类

   @Test
    public void addUserTest() throws IOException {
User user=new User("赵童","2000-02-18","男","宝鸡",5);
//        //4.使用SqlSession对象创建dao层代理对象
//         userDao = sqlSession.getMapper(UserDao.class);
        //5.使用代理对象执行方法
        userDao.addUser(user);
        System.out.println(user);
        System.out.println("----------------------------------------");
        //6.开启事务
        sqlSession.commit();
        System.out.println(user);



    }

注意:取值这里有两种方式#{} 和 ${}

  • #{} : 采取预编译方式
  • ${}:采取字符串拼接
6.3修改

1.在UserDao中添加方法

 /**
     * 修改信息
     */
    void updateUser(User user);

2.在UserDao.xml中配置该方法

 <!--修改信息-->
    <update id="updateUser" parameterType="com.wdzl.pojo.User">
        update user set address=#{address} where username=#{username}
    </update>

3.编写测试类

    @Test
    public void testUpdateUser(){
        User user=new User();
        user.setUsername("%童");
        user.setAddress("西安");
        List<User> userByName = userDao.findUserByName("%童");
        //5.使用代理对象执行方法
        List<User> users = userDao.findAll();
        //遍历
        for (User user2:userByName){
            System.out.println(user2);
        }


    }
6.4删除

1.在UserDao中添加方法

 /**
     * 删除
     */
    void deleteUser(User user);

2.在UserDao.xml中配置该方法

<!--删除信息-->
    <delete id="deleteUser" parameterType="com.wdzl.pojo.User">
        delete from user where username=#{username};
    </delete>

3.编写测试类

 @Test
    public void testDeleteUser(){
        User user=new User();
        user.setUsername("赵童");
        userDao.deleteUser(user);
        //5.使用代理对象执行方法
        List<User> users = userDao.findAll();
        //遍历
        for (User user2:users){
            System.out.println(user2);
        }


    }
6.5根据id查询用户信息

1.在UserDao中添加方法

  /**
     * 根据id查询用户信息
     */
    User findUserById(int id);

2.在UserDao.xml中配置该方法

  <!--根据id查询用户信息-->
    <select id="findUserById" parameterType="java.lang.Integer" resultType="com.wdzl.pojo.User">
        select *from user where id=#{id};
    </select>

3.编写测试类

   @Test
    public void testFindUserById(){
        User user=userDao.findUserById(3);
        System.out.println(user);
    }
6.6模糊查询

1.在UserDao中添加方法

 /**
     * 模糊查询
     *
     */
    List<User> findUserByName(String name);

2.在UserDao.xml中配置该方法

<!--模糊查询-->
    <select id="findUserByName" parameterType="String" resultType="com.wdzl.pojo.User">
        select * from user where username like #{username};
    </select>

3.编写测试类

  @Test
    public void testUpdateUser(){
        User user=new User();
        user.setUsername("%童");
        user.setAddress("西安");
        List<User> userByName = userDao.findUserByName("%童");
        //5.使用代理对象执行方法
        List<User> users = userDao.findAll();
        //遍历
        for (User user2:userByName){
            System.out.println(user2);
        }


    }
6.7查询用户总记录数

1.在UserDao中添加方法

 /**
     * 查询用户总记录数
     */
    int findTotal();

2.在UserDao.xml中配置该方法

<!--    查询用户总记录数-->
    <select id="findTotal" resultType="int" >
        select count(id) from user;
    </select>

3.编写测试类

   @Test
    public void testFindTotal(){
        int total = userDao.findTotal();
        System.out.println(total);
    }
6.8根据QueryVo查询用户信息

1.在UserDao中添加方法

  /**
     * 根据QueryVo查询用户信息
     */
    List<User> findUserByVo(QueryVo queryVo);

2.在UserDao.xml中配置该方法

  <!--根据包装类模糊查询用户数据信息-->
    <select id="findUserByVo" parameterType="com.wdzl.pojo.QueryVo" resultType="com.wdzl.pojo.User">
        select*from user where username like #{user.username}
    </select>

3.编写测试类

    @Test
    public void testFindByVo(){
        QueryVo queryVo=new QueryVo();
        User user=new User();
        user.setUsername("%德%");
        queryVo.setUser(user);
        List<User> userByVo = userDao.findUserByVo(queryVo);
        for (User user1:userByVo){
            System.out.println(user1);
        }

    }

keyProperty : 对应的实体类属性名

keyColumn :对应数据库列名

Order : 执行的顺序,after-在插入操作后执行

7.参数详解

7.1parameterType 输入类型
  1. 传递基本数据类型和 String

  2. 传递pojo对象

当传递参数为对象时,在sql语句中获取对象属性值需要使用OGNL表达式。

  • OGNL:Object Graphic Navigation Language 对象图导航语言
  • 它是通过对象的取值方式来获取值,在写法上把get给省略了
    • 在类中,我们获取值:user.getUsername();
    • 在OGNL中:user.userName
  • Mybatis中为什么能直接写userName,而不加 user. 呢?
    • 因为在 parameterType 中已经提供了属性所属的类,所以可以省略类名
7.2实体类属性与表字段不对应的问题解决

方案1:统一实体类和表字段的名称

方案2:给数据库字段加别名 ,让别名与实体类属性名统一

select id as userId

方案3:在UserDao.xml中配置对应关系

  <resultMap id="userMap" type="com.wdzl.pojo.User">
        <id property="uid" column="id"></id>
        <result property="username" column="username"></result>
    </resultMap>

8.MyBatis实现Dao层的开发

​ 准备:

新建工程,将前面演示CRUD操作的工程内容复制到该工程中,并做对应的修改

  • 复制 main 和 test 目录
  • 修改 pom.xml ,把相关依赖添加到配置文件中
  • 删除 UserDao 中的 ,并将下面标签中使用到 的地方换成
resultType="User"
8.1查询所有的方法(及其他操作)

1.添加UserDao对应的实现类

package com.wdzl.dao.impl;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;



import com.wdzl.dao.UserDao;

import com.wdzl.pojo.QueryVo;
import com.wdzl.pojo.User;

import java.util.List;

public class UserDaoImpl implements UserDao {
   private SqlSessionFactory factory;
   private SqlSession sqlSession;
  public UserDaoImpl(){

 }
 public UserDaoImpl(SqlSessionFactory factory){

      this.factory=factory;
      sqlSession=factory.openSession();
}

    /**
     * 查询用户列表
     * @return
     */
    @Override
    public List<User> findAll() {

        //2.调用sqlSession方法
        List<User> users=sqlSession.selectList("com.wdzl.dao.UserDao.findAll");
        return users;


}

    @Override
    public void addUser(User user) {

        //2.调用方法
        sqlSession.insert("com.wdzl.dao.UserDao.addUser",user);
        //3.提交事务
        sqlSession.commit();
        //4.释放资源
        sqlSession.close();

    }

    @Override
    public void updateUser(User user) {
        sqlSession.update("com.wdzl.dao.UserDao.updateUser",user);
        //3.提交事务
        sqlSession.commit();
        //4.释放资源
        sqlSession.close();

    }

    @Override
    public void deleteUser(User user) {
        sqlSession.delete("com.wdzl.dao.UserDao.deleteUser",user);
        //3.提交事务
        sqlSession.commit();
        //4.释放资源
        sqlSession.close();

    }

    @Override
    public User findUserById(int id) {
        User user=sqlSession.selectOne("com.wdzl.dao.UserDao.findUserById",id);
        return user;
    }


    @Override
    public List<User> findUserByName(String name) {
        List<User> user = sqlSession.selectList("com.wdzl.dao.UserDao.findUserByName",name);
        return user;
    }

    @Override
    public int findTotal() {
        Integer total=sqlSession.selectOne("com.wdzl.dao.UserDao.findTotal");

        return total;
    }

    @Override
    public List<User> findUserByVo(QueryVo queryVo) {
        return null;
    }
}

2.测试

package com.wdzl.dao;

import com.wdzl.dao.impl.UserDaoImpl;
import com.wdzl.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class UserDaoTest {
    InputStream is;
    SqlSessionFactoryBuilder builder;
    SqlSessionFactory factory;


    @Before
    public void init() throws IOException {
        //1.读取配置文件
        is = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.创建SqlSessionFactory工厂
        builder = new SqlSessionFactoryBuilder();
        factory =builder.build(is);

    }
    @After
    public void destroy() throws IOException {

        is.close();

    }
    @Test
    public void findAllTest() {


       UserDao userDao=new UserDaoImpl(factory);
        List<User> all = userDao.findAll();
        for (User a:all){
            System.out.println(a);
    }


    }

    @Test
    public void testAddUser(){
        User user = new User("唐康","2000-1-1","男","安康",0);
        UserDao userDao=new UserDaoImpl(factory);
        userDao.addUser(user);

    }

    @Test
    public void testUpdateUser(){
        User user = new User("唐康","2000-1-1","男","西安",0);
        UserDao userDao=new UserDaoImpl(factory);
        userDao.updateUser(user);
    }
    @Test
    public void deleteUser(){
        User user = new User("唐康",null,null,null,0);

        UserDao userDao=new UserDaoImpl(factory);
        userDao.updateUser(user);

    }

    @Test
    public void testFindUserById(){
        UserDao userDao = new UserDaoImpl(factory);
        User user=userDao.findUserById(2);
        System.out.println(user);


    }
    @Test
    public void testFindUserByName(){
        UserDao userDao = new UserDaoImpl(factory);
        List<User> user2 = userDao.findUserByName("赵童");
        for (User user1:user2){
            System.out.println(user1);
        }
    }
    @Test
    public void testFindTotal(){
        UserDao userDao = new UserDaoImpl(factory);
        int total = userDao.findTotal();
        System.out.println(total);
    }







}

9.properties标签

方式一:font>将配置提取出来进行统一管理,在需要使用的地方使用 ${} 引用即可

提取:

    <properties>
        <property name="driver" value="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
    </properties>

引用

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

方式二:引用外部配置文件

<properties resource="jdbc.properties"/>

引用外部有两个属性:

  • resource : 用于指定配置文件的位置类路径的写法,并且必须存在于类路径下
  • url : 统一资源定位符。可以标识资源的位置

10.typeAliases标签 和 package标签

<!--应用外部文件配置别名-->
    <typeAliases>

        <package name="com.wdzl.pojo"/>
<!--        <typeAlias type="com.wdzl.pojo.User" alias="aa"></typeAlias>-->
    </typeAliases>

在 typeAliases 中 有两个属性

  • type:用来指定起别名的实体类,如果省略 alias 属性,则使用默认别名,默认别名为类名 ,不区 分大小写,任意组合都可识别
  • alias:指定一个新的别名,比如上图案例中将别名设置为 hehe ,则在下面使用时使用 hehe 即可表 示User类。新的别名也不区分大小写

当实体类比较多时,我们可以使用 package 标签批量给包中的类添加别名

11.连接池

11.1概述

连接池就是用于存储连接对象的一个容器,当系统初始化完成后,容器被创建,容器会申请一些连 接对象,当用户访问数据库时,从容器中获取连接对象即可。访问完之后,会将连接对象归还给连接 池。这样做可以提高效率,提高连接对象的复用,不必频繁的创建和释放连接对象

11.22 MyBatis连接池

连接池有很多种,最为熟悉的比如c3p0,DBCP,druid等。

MyBatis支持三种内置的数据源类型:

POOLED: 实现dataSource接口,并且使用了池的思想。

UNPOOLED: 同样也是实现了dataSource接口,但是该类型并没有使用池的思想。

JDNI: 采用服务器提供的JDNI技术实现的,并且在不同服务器之间获取的连接池是不一样的。

当前框架教学使用的是Tomcat服务器,采用的是dbcp连接池技术

12.事务

对于事务的控制后期我们主要依赖于Spring来完成,当然MyBatis本身也是可以对事物进行控制 的。我们查看演示案例执行 addUser 方法时,我们会发现,Mybatis框架 默认事务提交方式是手动的。

我们可以通过 SqlSession 的构造方法进行设置操作。

session = factory.openSession(true);

再次执行 addUser() ,此时事务就会自动被提交。

13.动态SQL

13.1if标签
<!--根据给定条件 完成复合查询-->
<select id="findUserByConditions" parameterType="user" resultType="User">
select * from user where 1=1
<if test="username !=null">
and username=#{username}
</if>
</select>

13.2where标签

where标签是为了解决拼接sql时需要添加一个恒等式的问题

<where>
            <if test="ids !=null and ids.size()>0">
                <foreach collection="ids" open="and id in (" close=")" item="id" separator=",">
                    #{id}
                </foreach>
            </if>
        </where>
13.3foreach标签
<foreach collection="集合名" open="and id in (" close=")" item="变量名"
separator="分隔符">
#{变量名}
</foreach>

                <foreach collection="ids" open="and id in (" close=")" item="id" separator=",">
                    #{id}
                </foreach>

collection:遍历的集合

open:拼接SQL以该属性值为开头

close:拼接SQL以该属性值为结尾

item:变量名,相当于增强for循环中的那个变量。拼接在 open 和 close 之间

separator:元素(变量)间以什么分割

#{变量名}:必须与 item 属性保持一致

扩展标签

当配置文件中的相同的sql比较多时,我们可以将它统一提取出来

<sql id="userBase">
    select * from user
</sql>
<select id="findAll" resultType="user"><!--id属性对应方法的名称,不能随便写 -->
<include refid="userBase"></include>
/* select * from user;*/
</select>

14.MyBatis的多表查询

14.1MyBatis中的多表查询-多对一,一对多

1.数据库表:用户表 和 账户表

CREATE DATABASE mybatis2 CHARSET utf8;
USE mybatis2;
CREATE TABLE `user` (
`id` INT(10) NOT NULL AUTO_INCREMENT,
`username` VARCHAR(64) NOT NULL COMMENT '用户名称',
`birthday` DATETIME DEFAULT NULL COMMENT '生日',
`sex` CHAR(1) DEFAULT NULL COMMENT '性别',
`address` VARCHAR(256) DEFAULT NULL COMMENT '地址',
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO `user`(`id`,`username`,`birthday`,`sex`,`address`)
VALUES
(NULL,'老王','2017-05-27 18:27:09','男','北京'),
(NULL,'小王','2019-04-03 15:09:37','女','西安'),
(NULL,'小李','2019-07-22 17:44:33','女','咸阳'),
(NULL,'小刘','2018-03-04 15:52:36','男','渭南'),
(NULL,'大王','2016-11-03 17:37:26','男','富平'),
(NULL,'小马','2016-04-09 01:24:40','女','上海');
CREATE TABLE `account` (
`ID` INT(11) NOT NULL COMMENT '编号',
`UID` INT(11) DEFAULT NULL COMMENT '用户编号',
`MONEY` DOUBLE DEFAULT NULL COMMENT '金额',
PRIMARY KEY (`ID`),
KEY `FK_Reference_8` (`UID`),
CONSTRAINT `FK_Reference_8` FOREIGN KEY (`UID`) REFERENCES `user` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO `account`(`ID`,`UID`,`MONEY`) VALUES (1,2,1000),(2,1,1000),
(3,2,2000);

2.创建主配置文件:SqlMapConfig.xml,并且将log4j,jdbc的配置文件一起复制到 resources 目录下

<?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"/>
<typeAliases>
<package name="com.wdzl.pojo"/>
</typeAliases>
<environments default="mysql">
<!--配置mysql环境-->
<environment id="mysql">
<!--配置事务的类型-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源(连接池)-->
<dataSource type="POOLED"><!--Pooled 使用连接池-->
<!--配置连接数据库的4个基本信息-->
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<!--指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件-->
<mappers>
<mapper resource="com/wdzl/dao/UserDao.xml"/>
<mapper resource="com/wdzl/dao/AccountDao.xml"/>
</mappers>
</configuration>

3.建立两个实体类:用户实体类 和 账户实体类

User:

package com.wdzl.pojo;

import java.util.Date;
import java.util.List;

public class User {
    private int uid;
    private String username;
    private Date birthday;
    private char sex;
    private String address;
    //一个用户可以有多个账户
    private List<Account> accounts;

    @Override
    public String toString() {
        return "User{" +
                "uid=" + uid +
                ", username='" + username + '\'' +
                ", birthday=" + birthday +
                ", sex=" + sex +
                ", address='" + address + '\'' +
                ", accounts=" + accounts +
                '}';
    }

    public int getUid() {
        return uid;
    }

    public void setUid(int uid) {
        this.uid = uid;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Date getBirthday() {
        return birthday;
    }

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

    public char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public List<Account> getAccounts() {
        return accounts;
    }

    public void setAccounts(List<Account> accounts) {
        this.accounts = accounts;
    }

    public User(int uid, String username, Date birthday, char sex, String address, List<Account> accounts) {
        this.uid = uid;
        this.username = username;
        this.birthday = birthday;
        this.sex = sex;
        this.address = address;
        this.accounts = accounts;
    }

    public User() {
    }
}

Account:

package com.wdzl.pojo;

public class Account {
    private int aid;
    private int uid;
    private double money;

    //一个账户只属于一个用户
    private User user;

    @Override
    public String toString() {
        return "Account{" +
                "aid=" + aid +
                ", uid=" + uid +
                ", money=" + money +
                ", user=" + user +
                '}';
    }

    public int getAid() {
        return aid;
    }

    public void setAid(int aid) {
        this.aid = aid;
    }

    public int getUid() {
        return uid;
    }

    public void setUid(int uid) {
        this.uid = uid;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public Account(int aid, int uid, double money, User user) {
        this.aid = aid;
        this.uid = uid;
        this.money = money;
        this.user = user;
    }

    public Account() {
    }
}

4.创建各自实体类操作的接口

UserDao

package com.wdzl.dao;

import com.wdzl.pojo.User;

import java.util.List;

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

AccountDao

package com.wdzl.dao;

import com.wdzl.pojo.Account;

import java.util.List;

/**
 * 查询账户列表
 */
public interface AccountDao {
    List<Account> findAll();
}

5.创建各接口对应的映射配置文件

UserDao.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="com.wdzl.dao.UserDao"><!-- 对应dao层的全限定类名-->
    <resultMap id="UserAccountMap" type="user">
        <id property="uid" column="uid"></id>
        <result property="username" column="username"></result>
        <result property="birthday" column="birthday"></result>
        <result property="sex" column="sex"></result>
        <result property="address" column="address"></result>
        
        <collection property="accounts" ofType="account" column="uid">
            <id property="aid" column="aid"></id>
            <result property="uid" column="uid"></result>
            <result property="money" column="money"></result>
        </collection>
    </resultMap>
<!--查询用户列表-->
    <select id="findAll" resultMap="UserAccountMap">
       SELECT * FROM USER u LEFT OUTER JOIN account a ON u.uid=a.uid
    </select>


</mapper>




AccountDao.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="com.wdzl.dao.AccountDao">
<!--定义封装account和user的resultMap-->
    <resultMap id="accountUserMap" type="account">
        <id property="aid" column="aid"></id>
        <result property="uid" column="uid"></result>
        <result property="money" column="money"></result>

<!-- 配置一对一映射关系:配置user内容-->
        <association property="user" column="uid" javaType="user">
            <id property="uid" column="uid"></id>
            <result property="username" column="username"></result>
            <result property="birthday" column="birthday"></result>
            <result property="sex" column="sex"></result>
            <result property="address" column="address"></result>

        </association>
    </resultMap>
    <select id="findAll" resultMap="accountUserMap">
    SELECT a.aid,a.money,u.uid,u.username,u.sex,u.address FROM account a , USER u WHERE a.uid = u.uid
</select>
</mapper>

6.将映射配置文件添加到主配置文件中

<mappers>
<mapper resource="com/wdzl/dao/UserDao.xml"/>
<mapper resource="com/wdzl/dao/AccountDao.xml"/>
</mappers>

7.测试:分别测试UserDao 和 AccountDao

UserTest

import com.wdzl.dao.AccountDao;
import com.wdzl.dao.UserDao;
import com.wdzl.pojo.Account;
import com.wdzl.pojo.User;
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 org.apache.log4j.lf5.util.Resource;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;


public class UserTest {
    InputStream is;
    SqlSessionFactoryBuilder builder;
    SqlSessionFactory factory;
    SqlSession sqlSession;
    UserDao userDao;
    @Before
    public void init() throws IOException {
        //1.读取配置文件
        is = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.创建SqlSessionFactory工厂
        builder = new SqlSessionFactoryBuilder();
        factory =builder.build(is);
        //3.用工厂生产SqlSession对象
        sqlSession = factory.openSession();
        //4.使用SqlSession对象创建dao层代理对象
        userDao = sqlSession.getMapper(UserDao.class);

    }
    @After
    public void destroy() throws IOException {
        sqlSession.close();
        is.close();

    }
    @Test
    public void testFindAll(){
        List<User> all = userDao.findAll();
        for (User all1:all){
            System.out.println(all1);
        }
    }

}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qmzu7P5L-1616670375516)(D:\图片\QQ截图20210325182004.png)]

AccountTest

import com.wdzl.dao.AccountDao;
import com.wdzl.dao.UserDao;
import com.wdzl.pojo.Account;
import com.wdzl.pojo.User;
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 org.apache.log4j.lf5.util.Resource;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;


public class UserTest {
    InputStream is;
    SqlSessionFactoryBuilder builder;
    SqlSessionFactory factory;
    SqlSession sqlSession;
    UserDao userDao;
    @Before
    public void init() throws IOException {
        //1.读取配置文件
        is = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.创建SqlSessionFactory工厂
        builder = new SqlSessionFactoryBuilder();
        factory =builder.build(is);
        //3.用工厂生产SqlSession对象
        sqlSession = factory.openSession();
        //4.使用SqlSession对象创建dao层代理对象
        userDao = sqlSession.getMapper(UserDao.class);

    }
    @After
    public void destroy() throws IOException {
        sqlSession.close();
        is.close();

    }
    @Test
    public void testFindAll(){
        List<User> all = userDao.findAll();
        for (User all1:all){
            System.out.println(all1);
        }
    }

}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PsPMdZqm-1616670375517)(D:\图片\QQ截图20210325182101.png)]

14.2 MyBatis中的多表查询-2 多对多

SQL中多对多的关系需要借助一张中间

需求:查询角色信息的同时显示赋予该角色的用户信息

步骤: 1. 建立两张表,用户表 和 角色表

让用户表和角色表具有多对多的关系。需要使用中间表,中间表中包含这两张表的主键,并 且这两个主键在中间表中是外键

  1. 建立两个实体类:用户实体类 和 角色实体类

    让用户和角色实体类能体现出多对多的关系:各自包含对方的一个集合引用

  2. 建立配置文件

    用户配置文件

    角色配置文件

    1. 实现配置

      查询用户时,可以同时得到该用户所包含的角色信息。

      当我们查询角色时,可以同时得到拥有该角色的用户信息。

实现:先实现单表查询,再实现多对多关系查询

1.新建Module, 修改pom.xml,添加相应依赖

2.将多表查询1的Module中 src下的内容拷贝到当前Module中

3.将 Account有关的类,接口 ,配置文件等进行删除

实体类

接口

AccountDao配置文件

User实体类中与Account有关的属性和方法

UserDao.xml中有关Account的配置信息

测试类:Account测试类 和 User测试类中有关Account的部分

4.创建数据库表并插入数据

CREATE TABLE `role` (
`rid` INT(11) NOT NULL COMMENT '编号',
`ROLE_NAME` VARCHAR(30) DEFAULT NULL COMMENT '角色名称',
`ROLE_DESC` VARCHAR(60) DEFAULT NULL COMMENT '角色描述',
PRIMARY KEY (`rid`)5. 创建实体类
注意:本次实体类的属性名和表字段并没有匹配,所以我们需要去手动配置映射
) ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO `role`(`rid`,`ROLE_NAME`,`ROLE_DESC`) VALUES (1,'院长','管理整个学
院'),(2,'总裁','管理整个公司'),(3,'校长','管理整个学校');
CREATE TABLE `user_role` (
`UID` INT(11) NOT NULL COMMENT '用户编号',
`RID` INT(11) NOT NULL COMMENT '角色编号',
PRIMARY KEY (`UID`,`RID`),
KEY `FK_Reference_10` (`RID`),
CONSTRAINT `FK_Reference_10` FOREIGN KEY (`RID`) REFERENCES `role` (`rid`),
CONSTRAINT `FK_Reference_9` FOREIGN KEY (`UID`) REFERENCES `user` (`uid`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO `user_role`(`UID`,`RID`) VALUES (1,1),(3,1),(1,2);

5.创建实体类

Role:

package com.wdzl.pojo;

import java.util.List;

public class Role {
    private int rid;
    private String roleName;
    private String roleDesc;

    @Override
    public String toString() {
        return "Role{" +
                "rid=" + rid +
                ", roleName='" + roleName + '\'' +
                ", roleDesc='" + roleDesc + '\'' +
                ", users=" + users +
                '}';
    }

    public List<User> getUsers() {
        return users;
    }

    public void setUsers(List<User> users) {
        this.users = users;
    }

    //一个角色可以赋予多个用户
     private List<User> users;

    public int getRid() {
        return rid;
    }

    public void setRid(int rid) {
        this.rid = rid;
    }

    public String getRoleName() {
        return roleName;
    }

    public void setRoleName(String roleName) {
        this.roleName = roleName;
    }

    public String getRoleDesc() {
        return roleDesc;
    }

    public void setRoleDesc(String roleDesc) {
        this.roleDesc = roleDesc;
    }

    public Role(int rid, String roleName, String roleDesc) {
        this.rid = rid;
        this.roleName = roleName;
        this.roleDesc = roleDesc;
    }

    public Role() {
    }
}

6.创建Dao接口

public interface RoleDao {
/**
* 查询所有角色
*/
List<Role> findAll();
}

7.创建映射配置文件

<?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.wdzl.dao.RoleDao"><!--对应dao的全限定类名-->
<resultMap id="roleMap" type="com.wdzl.pojo.Role">
<id property="roleId" column="rid"></id>
<result property="roleName" column="ROLE_NAME"></result>
<result property="roleDesc" column="ROLE_DESC"></result>
</resultMap>
<select id="findAll" resultMap="roleMap">
select * from role
</select>
</mapper>

8.主配置文件中添加相应的映射文件配置

<mapper resource="com/wdzl/dao/RoleDao.xml"/>

9.测试单表查询是否成功

import com.wdzl.dao.RoleDao;
import com.wdzl.dao.UserDao;
import com.wdzl.pojo.Role;
import com.wdzl.pojo.User;
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 org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class RoleTest {
    InputStream is;
    SqlSessionFactoryBuilder builder;
    SqlSessionFactory factory;
    SqlSession sqlSession;
    RoleDao roleDao;
    @Before
    public void init() throws IOException {
        //1.读取配置文件
        is = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.创建SqlSessionFactory工厂
        builder = new SqlSessionFactoryBuilder();
        factory =builder.build(is);
        //3.用工厂生产SqlSession对象
        sqlSession = factory.openSession();
        //4.使用SqlSession对象创建dao层代理对象
        roleDao = sqlSession.getMapper(RoleDao.class);

    }
    @After
    public void destroy() throws IOException {
        sqlSession.close();
        is.close();

    }
    @Test
    public void testFindAll(){
        List<Role> all = roleDao.findAll();
        for (Role all1:all){
            System.out.println(all1);

        }
    }
}

10.多对多关系在实体类中进行体现

 //一个角色可以赋予多个用户
     private List<User> users;

11.分析SQL语句

12.测试

/**
* 查询角色
*/
@Test
public void testFindAllUser() {
List<Role> roles = roleDao.findAll();
for (Role role : roles) {
System.out.println(role);
System.out.println(role.getUsers());
}
}

15.延迟加载

延迟加载和立即加载

​ 延迟加载:在真正使用的时候才发起查询,不用的时候不查询。延迟加载也可以称为按需加载或懒加载。

​ 立即加载:无论数据是否使用,只要调用方法,就会立马执行查询

  <settings>
        <setting name="lazyLoadTriggerMethods" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>
    </settings>

16.缓存

概述:

​ 存在于内存中的数据叫做缓存

应用:

​ 减少和数据库的交互,提高执行效率

适用:

​ 经常查询并且不经常改变的。

​ 数据的正确与否对最终结果影响不大的。(比如视频访问量,回帖数量等)

不适用:

​ 经常改变的数据

​ 数据的正确与否对最终结果影响很大时(银行汇率,股票价格)

分类:

​ MyBatis中分为 一级缓存 和 二级缓存

16.1一级缓存

概述:

​ 它指的是MyBatis中SqlSession对象的缓存。当我们执行查询后,查询结果会存入到SqlSession为我 们提供的一款存储区域中。该区域的存储结构为Map。当我们再次查询同样数据时,MyBatis首先去一 级缓存中查询,如果存在,则直接拿取使用

注意:

​ 当SqlSession对象消失时,MyBatis的一级缓存也会消失

​ 当sqlSession调用 add , update , delete,commit , close方法时,MyBatis会自动清空一级缓存,防 止缓存数据与数据库中的数据不一致。

16.2二级缓存

概述:

​ 它指的是MyBatis中SqlSessionFactory对象的缓存。由同一个SqlSessionFactory对象创建的 SqlSession对象共享二级缓存。

17.MyBatis的注解开发

注意:

注解开发是为了简化映射配置文件,但是主配置文件还是存在。

环境搭建:

1.新建Module

2.修改pom.xml,添加相应的依赖

3.创建实体类User

4.创建主配置文件:SqlSessionConfig.xml

  • 引入外部配置文件
  • 配置别名
  • 配置数据源
  • 指定带有注解的dao层接口所在位置

5.创建UserDao

  • 声明findAll()方法
  • 在该方法上使用注解@Select

6.测试

  • 读取配置文件
  • 获取SqlSessionFactory对象
  • 使用Factory生成SqlSession
  • 使用SqlSession生成代理对象
  • 调用方法
  • 释放资源

7.注意事项:

​ 采用注解开发时,如果对应目录下还存在配置文件,及时在主配置文件中没有配置 xml ,运行时也会 报错。

  • 删除配置文件
  • 将配置文件移动到其他目录下

注解分类:

  • @Select
  • @Insert
  • @Delete
  • @Update
17.1注解一对多案例

接口

UserDao接口

package com.wdzl.dao;

import com.wdzl.pojo.User;
import org.apache.ibatis.annotations.Many;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.mapping.FetchType;

import java.util.List;

public interface UserDao {
    @Select("select*from user")
    @Results(id="userMap",value = {
            @Result(id = true,property = "uid",column = "uid"),
            @Result(property = "username",column = "username"),
            @Result(property = "birthday",column = "birthday"),
            @Result(property = "sex",column = "sex"),
            @Result(property = "address",column = "address"),
            @Result(property = "accounts",column = "uid",many = @Many(select = "com.wdzl.dao.AccountDao.findAccountByUid",
                    fetchType = FetchType.EAGER
            ))
    })
    List<User> findAll();

    @Select("select * from user where uid=#{uid}")
    User findUserByUid(Integer uid);


}

Account接口

package com.wdzl.dao;

import com.wdzl.pojo.Account;
import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.mapping.FetchType;

import java.util.List;

/**
 * 查询账户列表
 */
public interface AccountDao {
    @Select("select * from account")
    @Results(id="accountMap",value = {
            @Result(id=true,column = "aid",property = "aid"),
            @Result(column = "uid",property = "uid"),
            @Result(column = "money",property = "money"),
            @Result(column = "uid",property = "user",one=@One(
                    select="com.wdzl.dao.UserDao.findUserByUid",
                    fetchType = FetchType.EAGER
            ))
    })
    List<Account> findAll();

    @Select("select*from account where uid=#{uid}")
    Account findAccountByUid(Integer uid);
}

测试

UserTest

import com.wdzl.dao.AccountDao;
import com.wdzl.dao.UserDao;
import com.wdzl.pojo.Account;
import com.wdzl.pojo.User;
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 org.apache.log4j.lf5.util.Resource;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;


public class UserTest {
    InputStream is;
    SqlSessionFactoryBuilder builder;
    SqlSessionFactory factory;
    SqlSession sqlSession;
    UserDao userDao;
    @Before
    public void init() throws IOException {
        //1.读取配置文件
        is = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.创建SqlSessionFactory工厂
        builder = new SqlSessionFactoryBuilder();
        factory =builder.build(is);
        //3.用工厂生产SqlSession对象
        sqlSession = factory.openSession();
        //4.使用SqlSession对象创建dao层代理对象
        userDao = sqlSession.getMapper(UserDao.class);

    }
    @After
    public void destroy() throws IOException {
        sqlSession.close();
        is.close();

    }
    @Test
    public void testFindAll(){
        List<User> all = userDao.findAll();
        for (User all1:all){
            System.out.println(all1);
        }
    }

    @Test
    public void testFindUserById(){
      User user=  userDao.fin00dUserByUid(2);
        System.out.println(user);
    }

}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gkwv6M2S-1616670375518)(D:\图片\QQ截图20210325190128.png)]

AccountTest

import com.wdzl.dao.AccountDao;
import com.wdzl.dao.UserDao;
import com.wdzl.pojo.Account;
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 org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class AccountTest {
    InputStream is;
    SqlSessionFactoryBuilder builder;
    SqlSessionFactory factory;
    SqlSession sqlSession;
   AccountDao accountDao;
    @Before
    public void init() throws IOException {
        //1.读取配置文件
        is = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.创建SqlSessionFactory工厂
        builder = new SqlSessionFactoryBuilder();
        factory =builder.build(is);
        //3.用工厂生产SqlSession对象
        sqlSession = factory.openSession();
        //4.使用SqlSession对象创建dao层代理对象
        accountDao = sqlSession.getMapper(AccountDao.class);

    }
    @After
    public void destroy() throws IOException {
        sqlSession.close();
        is.close();

    }
    @Test
    public void testFindALL(){
        List<Account> all = accountDao.findAll();
        for (Account account:all){
            System.out.println(account);
        }

    }

}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LWXPBGjg-1616670375519)(D:\图片\QQ截图20210325190220.png)]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值