Mybatis详细总结

Mybatis

 

1.1常用框架

MVC框架:其实就是简化了Serviet的开发步骤

流行框架:1.Struts2

2.SpringMVC

持久层框架:完成数据库操作的框架

1.appache DBUtils

2.Hibernate

3.Spring JPA

4.MyBatis

胶水框架:Spring

SSM Spring+SpringMVC+Mybatis

1.2Mybatis介绍

mybatis是一个半自动的ORM框架

ORM (Object Relational Mapping)对象关系映射,将Java中的一个对象与数据表中一行记录——对应。

ORM框架提供了实体类与数据表的映射关系,通过映射文件的配置,实现对象的持久化(将对象保存到数据表中)。

mybatis的前身是ibatis

mybatis特点:

支持自定义sql,存储过程

对原有的JDBC进行了封装,几乎消除了所有JDBC代码,让开发者只需关注sQL本身

支持XML和注解配置方式自定完成ORM操作,实现结果映射,就是对象的属性和数据表列的对应关系

一.Mybatis部署

1创建Maven项目

1.java

2.web工程

2在项目中添加Mybatis依赖

1.在pom.xml中添加依赖

2.mybatis

<!--      mysql驱动  -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.27</version>
        </dependency>
​
<!--        mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.6</version>
        </dependency>
    </dependencies>

添加mybatis文件

创建自定义模板mybatis-config.xml

在resources中创建mybatis-config.xml

在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配置奇偶数据库连接信息-->
<!--    在environments标签中可以配置多个encvieronments,每个encvieronments可以配置一套数据库连接信息 -->
<!--     default属性,用来指定使用哪个environment标签-->
    <environments default="mysql">
        <environment id="mysql">
<!--            transactionManager 用于配置数据库管理方式-->
            <transactionManager type="JDBC"></transactionManager>
<!--            dataSource用于配置数据库连接信息-->
            <dataSource type="POOLED">
                <property name="drive" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/testkc?     characterEncoding=utf8&amp;useSSL=false&amp;serverTimezone=UTC&amp;allowMultiQueries=true"/>
                <property name="username" value="root"/>
                <property name="passworld" value="123456"/>
            </dataSource>
        </environment>
    </environments>
​
​
</configuration>

二.Mybatis框架使用

2.1.创建数据表

案例:学生信息的数据库操作

create table tb_students(
sid int PRIMARY KEY auto_increment,
stu_num char(5) NOT NULL UNIQUE,
stu_name VARCHAR(20) not null,
stu_gender CHAR(2) not null,
stu_age int not null
);

2.2创建实体类

Student.java

​
​
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
​
@Data//时间构造器
@AllArgsConstructor//全餐构造器
@NoArgsConstructor//无参构造器
@ToString//重写构造器
public class Student {
​
    private int stuID;
    private String stuNum;
    private String stuName;
    private String stuGender;
    private int stuAge;
}

2.3创建DAO接口,定义操作方法StydentDAO

public interface StudentDAO {
    public int insertStudent(Student student);
    public int deleteStudent(Student stuNum);
}
​

2.4创建DAO接口的映射文件

1.在resources目录下,新建名为mappers文件夹

2.在mappers中新建名为StudentMapper.xml的映射文件(根据模板创建)

3.在映射文件中对DAO中定义的方法进行实现:

<?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文件相当于DA0接口的‘实现类’,namespace属性要指定`实现DAO接口的全限定名 -->
<mapper namespace="com.hr.dao.StudentDAO">
<!--        id对应方法名 parameterType对应定实体类的路径-->
    <insert id="insterStudent"  parameterType="com.hr.pojo.Student">
        insert into tb_students(stu_num,stu_name,stu_gender,stu_age)
        values (#{stuNum},#{stuName},#{stuGender},#{stuAge})
    </insert>
    <delete id="deleteStudent">
        delete from  tb_students where stu_num=#{stuNum}
    </delete>
</mapper>

3.5将映射文件添加到主配置文件中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配置奇偶数据库连接信息-->
<!--    在environments标签中可以配置多个encvieronments,每个encvieronments可以配置一套数据库连接信息 -->
<!--    <! &#45;&#45; default属性,用来指定使用哪个environment标签&ndash;&gt;-->
    <environments default="mysql">
        <environment id="mysql">
<!--            transactionManager 用于配置数据库管理方式-->
            <transactionManager type="JDBC"></transactionManager>
<!--            dataSource用于配置数据库连接信息-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/testkc?characterEncoding=utf-8&amp;useSSL=false&amp;serverTimezone=UTC&amp;allowMultiQueries=true"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
<!--    添加的映射文件-->
    <mappers>
        <mapper resource="mappers/StudentMapper.xml"></mapper>
    </mappers>
​
</configuration>

三.单元测试

3.1添加单元测试的依赖

 <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.9</version>
            <scope>test</scope>
        </dependency>

3.2创建单元测试类

在被测试类后面alt+insert---选择Test

public interface StudentDAO {
    public int insertStudent(Student student);
    public int deleteStudent(Student stuNum);
}

3.3配置连接数据库 并实现增加操作

package com.hr.dao;
​
​
import com.hr.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 java.io.InputStream;
​
​
public class StudentDAOTest {
​
    @org.junit.Test
    public void insertStudent() {
        try {
​
​
        //加载mybatis配置文件
        InputStream is= Resources.getResourceAsStream("mybatis-config.xml");
​
        SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
        //会话连接工厂
        SqlSessionFactory factory=builder.build(is);
        //代表与数据库的连接
        SqlSession sqlSession=factory.openSession();
            //通过连接获得DAO对象
        StudentDAO studentDAO=sqlSession.getMapper(StudentDAO.class);
​
        //测试StudentDAO中得方法
        int i=studentDAO.insertStudent(new Student(0,"1001","张三","男",31));
        //添加事务管理需要手动提交
        sqlSession.commit();
            System.out.println(i);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    @org.junit.Test
    public void deleteStudent() {
        
    }
}

四.mybatis的CRUD操作(增删改查)

案例学生信息的曾山查改

5.1添加操作

5.2删除操作

根据学号删除学生信息

在StudentDAO中定义删除方法

public interface StudentDAO {
    public int insertStudent(Student student);
    public int deleteStudent(Student stuNum);
}

5.3.在StudentMapper.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文件相当于DA0接口的‘实现类’,namespace属性要指定`实现DAO接口的全限定名 -->
<mapper namespace="com.hr.dao.StudentDAO">
<!--        id对应方法名 parameterType对应定实体类的路径-->
    <insert id="insertStudent"  parameterType="com.hr.pojo.Student">
        insert into tb_students(stu_num,stu_name,stu_gender,stu_age)
        values (#{stuNum},#{stuName},#{stuGender},#{stuAge})
    </insert>
    <delete id="deleteStudent">
        delete from tb_students where stu_num=#{stuNum}
    </delete>
</mapper>
​

4.4在StdentDAO的测试类中添加测试方法

StdentDAOTest

package com.hr.dao;
​
​
import com.hr.pojo.Student;
import com.sun.deploy.util.SessionState;
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;
import java.io.Reader;
​
​
public class StudentDAOTest {
​
    @org.junit.Test
    public void insertStudent() {
        try {
​
​
            //加载mybatis配置文件
            InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
​
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            //会话连接工厂
            SqlSessionFactory factory = builder.build(is);
            //代表与数据库的连接
            SqlSession sqlSession = factory.openSession();
            //通过连接获得DAO对象
            StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class);
​
            //测试StudentDAO中得方法
            int i = studentDAO.insertStudent(new Student(0, "1001", "张三", "男", 31));
            //添加事务管理
            sqlSession.commit();
            System.out.println(i);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
​
    @org.junit.Test
    public void testDeleteStudent() {
        try {
            //以一个输入流的方式获取配置文件
            InputStream is=Resources.getResourceAsStream("mybatis-config.xml");
            //
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            // SqlSessionFactory表示Mybatis的会话工厂
            SqlSessionFactory factory = builder.build(is);
            //SqlSession表示Mybatis,数据之间的会话,通过工厂方法设计模式
            SqlSession sqlSession = factory.openSession();
            //通过SqlSession对象调用getMapper方法获取DAO接口对象
            StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class);
           int i=studentDAO.deleteStudent("1001");
           //提交事务方法
           sqlSession.commit();
           System.out.println(i);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
​

4.6添加更改操作

在xml映射文件中编写更改语句

根据stu—num更改学生信息

  <update id="updateStudent">
        update tb_students set stu_name=#{stuName},stu_gender=#{stuGender},
        stu_age=#{stuAge} where stu_num=#{stuNum}
    </update>

4.6编写实现update方法

testUpdaeStudent方法

   @Test
    public void testUpdateStudent() throws IOException {
        InputStream is=Resources.getResourceAsStream("mybatis-config.xml");
​
        SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
        //创建工厂模式
        SqlSessionFactory factory=builder.build(is);
        //通过会话获取DAO对象
        SqlSession sqlSession=factory.openSession();
        //测试StudentDAO中得方法
        StudentDAO studentDAO=sqlSession.getMapper(StudentDAO.class);
​
        int i=studentDAO.updateStudent(new Student(0,"1001","李四","女",18));
​
        sqlSession.commit();
        System.out.println(i);
    }

4.7实现查询方法

在xml映射文件中编写查询语句

<!--    第一种方式-->
<!--    <select id="listStudent" resultType="com.hr.pojo.Student" resultSets="java.util.List">-->
<!--        select sid as stuID ,stu_num stuNum,stu_name stuName,stu_gender stuGender,stu_age stuAge from tb_students-->
<!--    </select>-->
​
<!--    查询方法的第二种方式 resultMap id="" id可以随便起名字 type对象实体类的路径-->
<!--    resultMap标签用于定义实体类与数据映射表达映射关系(ORM)-->
    <resultMap id="studentMap" type="com.hr.pojo.Student">
        <id column="sid" property="stuID"/>
        <result column="stu_num" property="stuNum"/>
        <result column="stu_name" property="stuName"/>
        <result column="stu_gender" property="stuGender"/>
        <result column="stu_age" property="stuAge"/>
    </resultMap>
<!--resultMap用于应用一个实体类的映射关系,当配置了resultMap之后,resultType就可以省略-->
    <select id="listStudent"  resultMap="studentMap">
            select sid,stu_num,stu_name,stu_gender,stu_age from tb_students
      </select>

4.6编写实现ListStudent方法

testListStudent方法

@Test
    public void testListStudent() throws IOException {
        InputStream is=Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
        SqlSessionFactory factory=builder.build(is);
        SqlSession sqlSession=factory.openSession();
        StudentDAO studentDAO=sqlSession.getMapper(StudentDAO.class);
        List<Student> list=studentDAO.listStudent();
        sqlSession.commit();
        for (Student stu:list){
            System.out.println(stu);
        }
    }

4.7-查询一条操作

根据学生id查询一个学生的信息

在StudentDAO定义方法

public  Student quertStudent(String stuNum);

在xml映射文件中编写查询语句

  <resultMap id="studentMap" type="com.hr.pojo.Student">
        <id column="sid" property="stuID"/>
        <result column="stu_num" property="stuNum"/>
        <result column="stu_name" property="stuName"/>
        <result column="stu_gender" property="stuGender"/>
        <result column="stu_age" property="stuAge"/>
    </resultMap>
    
     <select id="quertStudent" resultMap="studentMap">
        select sid,stu_num,stu_name,stu_gender,stu_age from tb_students where stu_num=#{stuNum}
    </select>

在测试类 StudentDAOTest中编写查询方法

    @Test
    public void testQuertStudent() throws Exception{
        InputStream is=Resources.getResourceAsStream("mybatis-config.xml");
​
        SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
​
        SqlSessionFactory factory=builder.build(is);
​
        SqlSession sqlSession=factory.openSession();
​
        StudentDAO studentDAO=sqlSession.getMapper(StudentDAO.class);
​
        Student student=studentDAO.quertStudent("1003");
        sqlSession.commit();
        System.out.println(student);
    }

4.8查询总记录数

在接口中 StudentDAO中定义方法

  public int count();

在xml文件中配置查询语句

<!--统计数据条数 需要声明类型 resultType="int"-->
    <select id="count" resultType="int">
        select count(1) from  tb_students
    </select>

在测试类里面实现方法

  @Test
    public void count() throws Exception{
        InputStream is=Resources.getResourceAsStream("mybatis-config.xml");
​
        SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
​
        SqlSessionFactory factory=builder.build(is);
​
        SqlSession sqlSession=factory.openSession();
​
        StudentDAO studentDAO=sqlSession.getMapper(StudentDAO.class);
        int i=studentDAO.count();
        sqlSession.commit();
        System.out.println(i);
    }

4.9分页查询-多参数查询

分页查询(参数 start , pageSize)

在Student中定义操作方法,如果方法有多个参数,使用@Param注解声明参数的别名

//分页查询@Param 起别名
    public List<Student> listStudentByPage(@Param("start") int start,
                                           @Param(("pageSize")) int pageSize);

在StudentMapper.xml中配置时使用#{别名}获取指定的参数

 <resultMap id="studentMap" type="com.hr.pojo.Student">
        <id column="sid" property="stuID"/>
        <result column="stu_num" property="stuNum"/>
        <result column="stu_name" property="stuName"/>
        <result column="stu_gender" property="stuGender"/>
        <result column="stu_age" property="stuAge"/>
    </resultMap>
​
<!--  分页查询也可以用  limit #(agr0),#{arg1} 或者limit #(parm1),#{pageSize}-->
    <select id="listStudentByPage" resultMap="studentMap">
        select sid,stu_num,stu_name,stu_gender,stu_age from tb_students limit #{start},#{pageSize}
    </select>

社意如果DAQ操作方法没有通过@Param指定参数别名,在SQ.中也可以通过 arga,arg1. ..或者param1 , param2 ....获取婺数

5.10添加操作回填生成的主键

StudentMapper.xml

   <!-- useGeneratedKeys设置添加操作是否需要回填生成的主键-->
    <!-- keyProperty设置回填的主键值赋值到参数对象的哪个属情-->
    <insert id="insertStudent"  parameterType="com.hr.pojo.Student" useGeneratedKeys="true" keyProperty="stuID" >
        insert into tb_students(stu_num,stu_name,stu_gender,stu_age)
        values (#{stuNum},#{stuName},#{stuGender},#{stuAge})
    </insert>

五.mybatis工具类的封装

MybatisUtils

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 factory;
    //添加线程锁
    //在进行对象的跨层传递的时候,使用ThreadLocal可以避免多次传递,打破层次间的约束

    private  static final  ThreadLocal<SqlSession> local=new ThreadLocal<SqlSession>();
    //静态代码块 任何类启动时首先自动加载静态代码块

    static {
        //加载mybatis配置文件
        InputStream is = null;
        try {
            is = Resources.getResourceAsStream("mybatis-config.xml");
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            //会话连接工厂
            factory = builder.build(is);
        } catch (IOException e) {
            e.printStackTrace();
        }


    }

    //封装factory方法
    public static  SqlSessionFactory getFactory(){
        return factory;
    }
    //封装sqlSession会话
    public  static SqlSession getSqlSession() throws IOException {
        SqlSession sqlSession=local.get();
        if (sqlSession==null){
            sqlSession=factory.openSession();
            local.set(sqlSession);
        }
        return sqlSession ;
    }
    //    关闭Sqlsession
    public static void close(){
        SqlSession sqlSession=locol.get();
        if (sqlSession !=null){
            sqlSession.close();
            locol.set(null);
        }
    }
    //使用泛型封装getMapper
    public static <T extends Object>T getMapper(Class<T> c) throws IOException {
        SqlSession sqlSession=getSqlSession();
        return sqlSession.getMapper(c);
    }
}

六.事务管理

增删改都需要提交事务

SqlSession对象的作用

1.get.Mapper(DAO.class)获取Mapper(DAO接口的实例 )(也就是映射文件)

2.事务管理

当获取Session对象时就开启了事务

7.1手动管理事务

sqlSession.commit();提交事务

sqlSession.rollback();事务回滚

  @org.junit.Test
    public void insertStudent() throws IOException {
        //1.代表与数据库的连接 当我们获取sqlSession对象时,就默认开启了事务
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        try{
            //通过会话获得DAO对象
            StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class);
            //测试StudentDAO中的方法
            Student student=new Student(0, "1006", "懊悔", "男", 42);
            int i=studentDAO.insertStudent(student);
            //测试StudentDAO中得方法
            System.out.println(student);
            //2当操作完成并完成之后 需要手动提交事务管理
            sqlSession.commit();
        }catch (Exception e){
            //3当操作出现异常时,调用rollback方法 进行回滚
            sqlSession.rollback();
        }

    }

7.2自动提交事务

//通过SqLSessionFactory 调HjopenSession方法获取SqLSession对象时,可以通过参数设置事务是否自动提交

// 如果参数设置为true,表示自定提交事务:factory.openSession(true);

//如果参数设置为false,或者不设置参数,表示手动提交:factory .openSession() ; /factory.openSession(false);

MybatisUtils优化

1.给封装SqlSession方法添加了一个boolean isAutoCommit 参数

2.获取getMapper的时候传了一个true

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 factory;
    //添加线程锁
    //在进行对象的跨层传递的时候,使用ThreadLocal可以避免多次传递,打破层次间的约束

    private  static final  ThreadLocal<SqlSession> local=new ThreadLocal<SqlSession>();
    //静态代码块 任何类启动时首先自动加载静态代码块

    static {
        //加载mybatis配置文件
        InputStream is = null;
        try {
            is = Resources.getResourceAsStream("mybatis-config.xml");
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            //会话连接工厂
            factory = builder.build(is);
        } catch (IOException e) {
            e.printStackTrace();
        }


    }

    //封装factory方法
    public static  SqlSessionFactory getFactory(){
        return factory;
    }

    //封装sqlSession会话
    public  static SqlSession getSqlSession(boolean isAutoCommit) throws IOException {
        SqlSession sqlSession=local.get();
        if (sqlSession==null){
            //通过SqLSessionFactory 调HjopenSession方法获取SqLSession对象时,可以通过参数设置事务是否自动提交
            // 如果参数设置为true,表示自定提交事务:factory.openSession(true);
            //如果参数设置为false,或者不设置参数,表示手动提交:factory .openSession() ; /factory.openSession(false);
            sqlSession=factory.openSession(isAutoCommit);
            local.set(sqlSession);
        }
        return sqlSession ;
    }
    //封装getSession方法 手动提交用getSession
    public static  SqlSession getSqlSession() throws IOException {
        return getSqlSession(false);
    }
    //使用泛型封装getMapper 自动提交用getMapper
    public static <T extends Object>T getMapper(Class<T> c) throws IOException {
        SqlSession sqlSession=getSqlSession(true);
        return sqlSession.getMapper(c);
    }

测试操作

   @org.junit.Test
    //自动提交
    public void testDeleteStudent() throws IOException {
            StudentDAO studentDAO=MybatisUtils.getMapper(StudentDAO.class);
           int i=studentDAO.deleteStudent("1001");
           //提交事务方法
           System.out.println(i);

    }

业务逻辑层自动事务管理

public class StudentServiceimpl implements StudentService {
    private StudentDAO studentDAO= MybatisUtils.getMapper(StudentDAO.class);

    public StudentServiceimpl() throws IOException {

    }

    @Override
    public boolean addStudent(Student student) {
        int i=studentDAO.insertStudent(student);
        boolean b=i>0;
        return b;
    }
}

七.Mybatis主配置文件

mybatis-config.xml是Mybatis框架的主配置信息,只用于配置Mybatis数据源及属性信息

7.1properties标签

在resources目录下创建jdbc.properties文件用于键值对配置

mysql_driver=com.mysql.jdbc.Driver
mysql_url=jdbc:mysql://localhost:3306/db_mybatis
mysql_username=root
mysql_password=123456

在mybatis-config.xml中通过properties标签引用jdbc.properties文件;引入之后,在配置environment时可以直接使用jdbc.properties的key获取对应的value

8.2setting标签

<!--    setting标签用于设置mybatis工作属性-->
    <settings>
<!--        启动二级缓存-->
        <setting name="cachEnable" value="true"/>
<!--        启动延迟加载-->
        <setting name="lazyLoadingEnable" value=""/>
    </settings> 

8.3typeAliase标签 用于起别名

<!-- <typeAliases> 标签用于给实体类起别名 ,在映射文件中可以直接使用别名来替代实体类的全限定名-
   -->
    <typeAliases>
        <typeAlias type="com.hr.pojo.Student" alias="Student"/>
    </typeAliases>

8.4plugins标签

<!-- plugins用于配置mybatis插件例如(分页插件)   -->
    <plugins>
        <plugin interceptor=""></plugin>
    </plugins>

8.5environments标签

<!--    在environments配置奇偶数据库连接信息-->
<!--    在environments标签中可以配置多个encvieronments,每个encvieronments可以配置一套数据库连接信息 -->
<!--    <! &#45;&#45; default属性,用来指定使用哪个environment标签&ndash;&gt;-->
    <environments default="mysql">
        <environment id="mysql">
<!--            transactionManager 用于配置数据库管理方式-->
<!--            type="JDBC'以进行事务的提交和回滚操作-->
<!--            type="MANAGED”依赖容器定成事务肾理,本身不进行事务的提交和回滚操作&ndash;&gt;-->

            <transactionManager type="JDBC"></transactionManager>
<!--            dataSource用于配置数据库连接信息 type="POOLED"/type="UNPOOLED"-->
            <dataSource type="POOLED">
                <property name="driver" value="${mysql_driver}"/>
                <property name="url" value="${mysql_url}"/>
                <property name="username" value="${mysql_username}"/>
                <property name="password" value="${mysql_password}"/>
            </dataSource>
        </environment>
    </environments>

8.6mapper标签

加载映射配置 (映射文件,DAO注解)

<!--mapper用于载入映射文件 有多少个mapper载入多少    添加的映射文件-->
 <mappers>
     <mapper resource="mappers/StudentMapper.xml"></mapper>
 </mappers>

九.映射文件

9.1Mybatis的初始化

正在上传…重新上传取消

9.2Mapper跟标签

mapper文件相当于0AO接口的实现类',namespace属性要指定实现DAO接口的全限定名

9.3insert标签

声明添加操作(sql:insert.....)

常用属性

id属性:绑定DAO声明的方法名

parameterTpye属性,用以指定接口中对应的方法的参数的类型(可省略

useGeneratedKeys属性,设置添加操作是否需要回填生成的主键

kevPreperty属性,指定回填的id设置到参数对象中的哪个属性 timeout属性,设置此操作的超时时间,如果不设置则一直等待

主键回填

<!--        id对应方法名 parameterType对应定实体类的路径-->
    <!-- useGeneratedKeys设置添加操作是否需要回填生成的主键-->
    <!-- keyProperty设置回填的主键值赋值到参数对象的哪个属情 也就是主键自增   -->
    <insert id="insertStudent"  parameterType="com.hr.pojo.Student" useGeneratedKeys="true" keyProperty="stuID" >
        insert into tb_students(stu_num,stu_name,stu_gender,stu_age)
        values (#{stuNum},#{stuName},#{stuGender},#{stuAge})
    </insert>
<insert id="insertStudent" >  
    <selectKey keyProperty="stuID" resultType="java.lang.Integer">        select last_insert_id()    
    </selectKey>>   
    insert into tb_students(stu_num,stu_name,stu_gender,stu_age)    values (#{stuNum},#{stuName},#{stuGender},#{stuAge})
</insert>

9.4delete标签

声明操作

9.5upadte标签

声明修改操作

9.6select标签

声明查询操作

id属性,指定绑定方法的方法名

parameterType属性,设置参数类型 resultType属性,指定当前sql返回数据封装的对象类型(实体类)

resultMap属性,指定从数据表到实体类的字段和属性的对应关系

useCache属性查询此操作是否需要缓存

timeout ,设置超时时间

9.7resultMap标签

<!--    查询方法的第二种方式 resultMap id="" id可以随便起名字 type对象实体类的路径-->
<!--    resultMap标签用于定义实体类与数据映射表达映射关系(ORM)-->
    <resultMap id="studentMap" type="Student">
        <id column="sid" property="stuID"/>
        <result column="stu_num" property="stuNum"/>
        <result column="stu_name" property="stuName"/>
        <result column="stu_gender" property="stuGender"/>
        <result column="stu_age" property="stuAge"/>
    </resultMap>

9.8cache标签

设置当前DAO进行数据库操作时的缓存属性设置

<cache type="" size="" readOnly="false"/>

9.9sqlincould

十.分页插件

分页插件是一个独立于Mybatis框架之外的第三方插件

10.1添加分页插件的依赖

pageHelper

<!-- pagehelpe分页插件依赖 -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>5.1.10</version>
        </dependency>

10.2配置插件

在mybatis的主配置文件 mybatis-config.xml中通过plugins标签进行配置

<!-- plugins用于配置mybatis插件例如(分页插件)   -->
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
    </plugins>

10.3分对学生信息进行分页查询

StudentDAO studentDAO=MybatisUtils.getMapper(StudentDAO.class);
        PageHelper.startPage(1,3);
        List<Student> students=studentDAO.listStudent();
        PageInfo<Student> pageInfo=new PageInfo<Student>(students);
        //pageInfo中就包含了数据及分页信息
        List<Student>  list=pageInfo.getList();
        for (Student stu:list
             ) {
            System.out.println(stu);
        }

10.4带条件分页

测试方法

/    带条件分页方法实现
    @Test
    public void testListStudentByGender() throws IOException {
        StudentDAO studentDAO=MybatisUtils.getMapper(StudentDAO.class);
        PageHelper.startPage(1,1);
        List<Student> students=studentDAO.listStudentByGender("女");
        PageInfo pageInfo=new PageInfo<Student>(students);
        List<Student> list=pageInfo.getList();
        for (Student s:list
             ) {
            System.out.println(s);
        }

xml 配置执行语句

  <select id="listStudentByGender" resultMap="studentMap">
        select <include refid="studentset"/> from tb_students where stu_gender=#{stuGender}
 </select>

DAO定义的方法

   //带条件分页方法
        public List<Student> listStudentByGender(String gender);

十一.关联映射

11.1实体关系

实体――数据实体,实体关系指的就是数据与数据之间的关系例如:

用户和角色、房屋和楼栋、订单和商品

实体关系分为一下四种:

  • ·实例:一对一关联:人和身份证、学生和学生证、用户基本信息和详情

    用户信息(30个字段,用户数量也很多)

数据表关系:

  • 主键关联(用户表主键和详情表主键相同时,表示是匹配的数据)

  • 唯一外键关联

用户基本信息表(5个字段) 用户详情表(20+) 用户ID,帐号,密码,姓名,最后登录时间 详情ID, 手机 …… uid(外键,唯一)

1 zhangsan........ 1 130395358 2

2 list 3 154964988 3

3 wangwu 2 1649766495 1

用户登录:根据用户名查询用户信息,当用户表中数据量很大且字段很多时会严重影响查询的速度

一对多关联:多对一关联

实例

  • 一对多 班级和学生 类别和商品

  • 多对一 学生和班级 商品和类别

数据表关系:

  • 在多的一端添加外键和一对一段进行关联

多对多关联

实例:用户和角色,角色和权限,房屋和业主,学生和社团订单和商品

数据表关系:建立第三张关系表添加两个外键分别与两张表的主键关联

用户(userid) 用户角色表(uid.id) 角色(role_id)

11.2创建项目,部署Mybatis框架

步骤略

创建web项目(Maven)

<!--添加web依赖-->
    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

部署mybatis框架

  • 添加依赖

  <!--        添加mybatis依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.6</version>
        </dependency>
 <!--     添加mysql驱动  -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.27</version>
        </dependency>

配置文件

jdbc

mysql_driver=com.mysql.jdbc.Driver
mysql_url=jdbc:mysql://localhost:3306/db_mybatis
mysql_username=root
mysql_password=123456

  • <?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>
    <!--    用来引用jdbc文件-->
        <properties resource="jdbc.properties">
    
        </properties>
        <environments default="mysql">
            <environment id="mysql">
    <!--            事务管理 jdbc-->
                <transactionManager type="JDBC"></transactionManager>
    <!--           数据库的连接池-->
                <dataSource type="POOLED">
                    <property name="driver" value="${mysql_driver}"/>
                    <property name="url" value="${mysql_url}"/>
                    <property name="username" value="${mysql_username}"/>
                    <property name="password" value="${mysql_password}"/>
                </dataSource>
            </environment>
        </environments>
    </configuration>
    

    帮助类

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

public class MybatisUtils {


    private static SqlSessionFactory factory;
    private static  final  ThreadLocal<SqlSession> locol=new ThreadLocal<SqlSession>();


    static {
        try {
            InputStream is= Resources.getResourceAsStream("mybatis-config.xml");

            SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
            factory=builder.build(is);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    public static SqlSessionFactory SqlSessionFactory() {
        return factory;
    }

    private static SqlSession  getSqlSession(boolean isAutoCommit){
        SqlSession sqlSession=locol.get();
        if (sqlSession==null){
            sqlSession=factory.openSession(isAutoCommit);
            locol.set(sqlSession);
        }
        return sqlSession;
    }
    //手动提交
    public static  SqlSession getSqlSession(){
        return  getSqlSession(false);
    }
    //自动提交
    public static <T extends Object> T getMapper(Class<T> c){
            SqlSession sqlSession= getSqlSession(true);
            return sqlSession.getMapper(c);
    }
}

11.3一对一关联

用户-----和详情

11.3.1创建数据表

User

--用户信息表
create table users(
    user_id int primary key auto_increment,
    user_name varchar(20) not null uunique,
    user_pwd varchar(20) not null,
    user_realname varchar(20) not null,
    user_img varchar(100) not null
);

Detail

-----用户详情表
create table details(
	detail_id int primary key auto_increment,
	user_addr varchar(50) not null,
    user_tel char(11) not null,
    user_desc varchar(200),
    uid int not null unique,
   	--constraint FK_USER foreign key(uid) references users(user_id)
);

添加unique表示唯一外键,只能连接一个表做外键

constraint FK_USER foreign key(uid) references users(user_id) 物理关联

11.3.3创建DAO中的方法

方法
package com.hr.Dao;import com.hr.pojo.User;public interface UserDAO { public int insertUser(User user); public User queryUser(String username);}

添加操作

添加查询操作
package com.hr.Dao;

import com.hr.pojo.Detail;
import com.hr.pojo.User;
import com.hr.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import javax.xml.crypto.Data;

import static org.junit.Assert.*;

public class UserDAOTest {
    @Test
    public  void testInsertUser(){
        User user=new User(0,"gsgdg","123444","啊鬼打鬼","13.jpg",null);
        Detail detail=new Detail(0,"湖北武汉市","136556558","要发三个傻瓜",0);
        SqlSession  sqlSession=MybatisUtils.getSqlSession();
        try {
            //1
            UserDAO userDAO= sqlSession.getMapper(UserDAO.class);
            int i=userDAO.insertUser(user);
            System.out.println(user);
            System.out.println(i);
            //2将user表 获取的回填userid给detail表 这样detail表也拥有了回填userid
            detail.setUserId( user.getUserId() );
            //3
            DetailDAO detailDAO=sqlSession.getMapper(DetailDAO.class);
            int j=detailDAO.InsertDetail(detail);
            System.out.println(detail);
            System.out.println(j);
            //手动提交事务
            sqlSession.commit();
        }catch (Exception e){
            e.printStackTrace();
            //是无回滚 防止一个运行失败 另一个运行成功
            sqlSession.rollback();
        }

    }
    @Test
    public void testQueryUser(){
        UserDAO userDAO=MybatisUtils.getMapper(UserDAO.class);
        User user=userDAO.queryUser("zhangsan");
        System.out.println(user);
    }
}

11.3.4一对一关联查询

在查询用户的同时关联查询出与之对应的详情

  • 实体

UserDetail
  • 映射文件

    1.第一种连接查询

    <resultMap id="UserMap" type="User">
            <id column="user_id" property="userId"/>
            <result column="user_name" property="userName"/>
            <result column="user_pwd" property="userPwd"/>
            <result column="user_realname" property="userRealname"/>
            <result column="user_img" property="userImg"/>
            <result column="detail_id" property="detail.detailId"/>
            <result column="user_addr" property="detail.userAddr"/>
            <result column="user_tel" property="detail.userTel"/>
            <result column="user_desc" property="detail.userDesc"/>
    
        </resultMap>
    
        <select id="queryUser" resultMap="UserMap">
            select user_id,user_name,user_pwd,user_realname,user_img,detail_id,user_addr,user_tel,user_desc
            from users u
            inner join
            details d
            on u.user_id=d.uid
            where user_name=#{userNmae}
        </select>

    2.第二种子查询

    tebailMapper.xml字表查询

    <resultMap id="com.hr.pojo.Detail" type="Detail">
            <id column="detail_id" property="detailId"/>
            <result column="user_addr" property="userAddr"/>
            <result column="user_tel" property="userTel"/>
            <result column="user_desc" property="userDesc"/>
        </resultMap>
        <select id="QuertDetailByuid" resultMap="Detail">
            select detail_id user_addr,user_tel,user_desc
            from details
            where uid=#{userId}
        </select>
       <resultMap id="UserMap" type="User">
            <id column="user_id" property="userId"/>
            <result column="user_name" property="userName"/>
            <result column="user_pwd" property="userPwd"/>
            <result column="user_realname" property="userRealname"/>
            <result column="user_img" property="userImg"/>
    <!--        association调用子查询 关联查询一个对象-->
            <association property="deatil" select="com.hr.Dao.DetailDAO.QuertDetailByuid" column="user_id"/>
        </resultMap>
    
        <select id="queryUser" resultMap="UserMap">
            select user_id,user_name,user_pwd,user_realname,user_img
            from users
            where user_name=#{userNmae}
        </select>

    UserMapper.xml查询

11.4一对多

案例:班级(1)对学生(n)

11.4.1

--创建班级信息表
create table classes(
	cid int primary key auto_increment,
    cname varchar(30) not null unique,
    cdesc varchar(100)
);
--创建学生信息表
create table students(
	sid char(5) not null,
    sname varchar(20) not null,
    sage int not null,
    scid int null
);

11.4.2创建实体类

班级学生

11.4.3关联查询

当查询一个班级的时候,要关联查询出这个班的所有学生

连接查询

    <resultMap id="classMap" type="Clazz">
        <id column="cid" property="classId"/>
        <result column="cname" property="className"/>
        <result column="cdesc" property="classDesc"/>
<!--        Clazz对象的stus属性是一个list标签 需要使用collection标签-->
<!--        collection标签中 ofType属性声明的是集合中元素的类型-->
        <collection property="stus" ofType="Student">
            <result column="sid" property="stuId"/>
            <result column="sname" property="stuName"/>
            <result column="sage" property="stuAge"/>
        </collection>
    </resultMap>
    <select id="queryClass" resultMap="classMap">
        select cid,cname,cdesc,sid,sname,sage
        FROM classes c INNER JOIN students s
        on c.cid=s.scid
        WHERE c.cid=1;
    </select>

子查询

咋查询的映射配置
<?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.hr.Dao.StudentDAO">

    <resultMap id="StudentMap" type="Student">
        <id column="sid" property="stuId"/>
        <result column="sname" property="stuName"/>
        <result column="sage" property="stuAge"/>
        <result column="scid" property="stuCid"/>

    </resultMap>
    <select id="listStudentByid" resultMap="StudentMap">
            select sid,sname,sage,scid from students where scid=#{cid}
    </select>
</mapper>
    <resultMap id="classMap" type="Clazz">
        <id column="cid" property="classId"/>
        <result column="cname" property="className"/>
        <result column="cdesc" property="classDesc"/>
        <collection property="stus" select="com.hr.Dao.StudentDAO.listStudentByid" column="cid"/>
    </resultMap>
    <select id="queryClass" resultMap="classMap">
        select cid,cname,cdesc
        FROM classes
        WHERE cid=#{classID};
    </select>

studentDAO方法定义

ClassDAO方法定义

11.5一对多关联

实例 学生(n)对班级(1)

当查询这个学生的时候,关联查询这个学生所在的班级

  • 连接查询

连接查询的映射配置 Student.xml
    <!--    多对一查询-->
    <!--    方法一连接查询-->

    <resultMap id="studentMap" type="Student">
        <id column="sid" property="stuId"/>
        <result column="sname" property="stuName"/>
        <result column="sage" property="stuAge"/>
        <result column="cid" property="clazz.classId"/>
        <result column="cname" property="clazz.className"/>
        <result column="cdesc" property="clazz.classDesc"/>
    </resultMap>
    <select id="queryStudentByid" resultMap="studentMap">
        select sid,sname,sage,scid,cid,cname,cdesc from students s inner join classes c on s.scid=c.cid where s.sid=#{stuId}
    </select>
  • 子查询

子查询映射配置 ClassMapper.xml 和StudentMapper.xml

11.6多对多连表查询

案例 学生(n)对课程(n)

11.6.1创建课程数据表

--学生信息表如上
--课程信息表
create table courses(
course_id int primary key auto_increment,
course_name varchar(50) not null
);
--选课信息表/成绩表
create table grades(
sid char(5) not null,
cid int not null,
score int not null

)

11.6.2关联查询

查询学生时,同时查询学生学生选择的课程

StudentCourse

根据课程编号查询课程时,同时查询了选择这门课程的学生信息

StudentCourse

连接查询映射配置CourseMapper.xml
    <resultMap id="courseMap" type="Course">
        <id column="course_id" property="courseId"/>
        <result column="course_name" property="courseName"/>
        <collection property="students" ofType="Student">
            <result column="sid" property="stuId"/>
            <result column="sname" property="stuName"/>
            <result column="sage" property="stuAge"/>
        </collection>
    </resultMap>
    <select id="queryCoursesByid" resultMap="courseMap">
        select course_id,course_name,s.sid,sname,s.sage
FROM
courses c inner join grades g
INNER JOIN students s
on c.course_id=g.cid and g.sid=s.sid
where c.course_id=1
    </select>
  • 在查询映射配置

StudentMapper.xmlCourseMapper.xml

StudentMapper.xml

   <resultMap id="StudentMap2" type="Student">
        <id column="sid" property="stuId"/>
        <result column="sname" property="stuName"/>
        <result column="sage" property="stuAge"/>
    </resultMap>
    <select id="queryStudentBycourseId" resultMap="StudentMap2">
        select s.sid,sname,sage FROM
students s
INNER JOIN
grades g
on
s.sid=g.sid where g.cid=1
    </select>

CourseMapper.xml

    <resultMap id="courseMap" type="Course">
        <id column="course_id" property="courseId"/>
        <result column="course_name" property="courseName"/>
        <collection property="students" select="com.hr.Dao.StudentDAO.queryStudentBycourseId" column="course_id"/>
    </resultMap>
    <select id="queryCoursesByid" resultMap="courseMap">
        select course_id,course_name FROM courses
where course_id=#{courseId}
    </select>

十二、动态sql

12.1什么是动态sql

根据查询条件动态完成SQL的拼接

12.2动态SQL使用案例

案例:心仪对象搜索

12.2.1创建数据表

create table members(
member_id int primary key auto_increment,
member_nick varchar(20) not null unique,
member_gender char(2) not null,
member_age int not null,
member_city varchar(30) not null
);

12.2.2创建实体类

//@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Memebr {
    private  int memberId;
    private String memberNick;
    private  String memberGender;
    private int memberAge;
    private String memberCity;

12.2.3创建DAO接口

在DAO接口中定义一个或者多个条件查询的方法

public interface MemberDAO{
    //再多条件查询中,如果查询条件不确定,可以直接使用HashMap作为参数,
    //优点:无需单独定义传递查询条件的类
    //缺点:当/向Map中存放参数时. key必须与动态sqL保持一致()
//    public List<Member> searchMember(HashMap<String,Object> params);
    //也可以定义专门用于存放查询条件的实体类存放参数
    //优点:设置参数时 无需关注属性名
    //缺点:需要单独定义一个类单独封装
    public List<Member> searchMember(MemberSearchCondition params);
}

在定义一个实体类存放参数

@NoArgsConstructor
@AllArgsConstructor

public class MemberSearchCondition {
    private String gender;
    private Integer minAge;
    private Integer maxAge;
    private String City;

动态创建 MemberMapper.xml的sql语句

12.2.4 if方法

   <resultMap id="memberMap" type="Member">
        <id column="member_id" property="memberId"/>
        <result column="member_nick" property="memberNick"/>
        <result column="member_gender" property="memberGender"/>
        <result column="member_age" property="memberAge"/>
        <result column="member_city" property="memberCity"/>
    </resultMap>
<!--第一种方法 where 1=1 才能保证添加and 不报错 第二种是where标签 忽略了and-->
<!--  <trim prefix="where" prefixOverrides="and | or" suffix="order by member_age"> 前缀prefix定义的是方法 prefixOverrides是定义的忽略and or
   suffix后缀 order by member_age 排序-->
    <select id="searchMember" resultMap="memberMap">
            select member_id,member_nick,member_gender,member_age,member_city from members
           	where 1=1
            <if test="gender !=null"><!---gender就是参数对象的属性/参数Map的key-->
               and member_gender=#{gender}
            </if>
            <if test="minAge !=null">
                and member_age &gt;=#{minAge}<!--&gt; 是>号的意思-->
            </if>
            <if test="maxAge !=null">
                and member_age &lt;=#{maxAge}<!--&lt; 是<号的意思-->
            </if>
            <if test="City !=null">
            and member_city=#{City}<!--&lt; 是<号的意思-->
            </if>
           
    </select>

12.2.5<where>标签方法

  <resultMap id="memberMap" type="Member">
        <id column="member_id" property="memberId"/>
        <result column="member_nick" property="memberNick"/>
        <result column="member_gender" property="memberGender"/>
        <result column="member_age" property="memberAge"/>
        <result column="member_city" property="memberCity"/>
    </resultMap>
<!--第一种方法 where 1=1 才能保证添加and 不报错 第二种是where标签 忽略了and-->
<!--  <trim prefix="where" prefixOverrides="and | or" suffix="order by member_age"> 前缀prefix定义的是方法 prefixOverrides是定义的忽略and or
   suffix后缀 order by member_age 排序-->
    <select id="searchMember" resultMap="memberMap">
            select member_id,member_nick,member_gender,member_age,member_city from members
           	<where>
            <if test="gender !=null"><!---gender就是参数对象的属性/参数Map的key-->
               and member_gender=#{gender}
            </if>
            <if test="minAge !=null">
                and member_age &gt;=#{minAge}<!--&gt; 是>号的意思-->
            </if>
            <if test="maxAge !=null">
                and member_age &lt;=#{maxAge}<!--&lt; 是<号的意思-->
            </if>
            <if test="City !=null">
            and member_city=#{City}<!--&lt; 是<号的意思-->
            </if>
           </where>
    </select>

12.2.6<trim>方法

<mapper namespace="com.hr.Dao.MemberDAO">
    <resultMap id="memberMap" type="Member">
        <id column="member_id" property="memberId"/>
        <result column="member_nick" property="memberNick"/>
        <result column="member_gender" property="memberGender"/>
        <result column="member_age" property="memberAge"/>
        <result column="member_city" property="memberCity"/>
    </resultMap>
<!--第一种方法 where 1=1 才能保证添加and 不报错 第二种是where标签 忽略了and-->
<!--  <trim prefix="where" prefixOverrides="and | or" suffix="order by member_age"> 前缀prefix定义的是方法 prefixOverrides是定义的忽略and or
   suffix后缀 order by member_age 排序-->
    <select id="searchMember" resultMap="memberMap">
            select member_id,member_nick,member_gender,member_age,member_city from members
            <trim prefix="where" prefixOverrides="and | or" suffix="order by member_age">
            <if test="gender !=null"><!---gender就是参数对象的属性/参数Map的key-->
               and member_gender=#{gender}
            </if>
            <if test="minAge !=null">
                and member_age &gt;=#{minAge}<!--&gt; 是>号的意思-->
            </if>
            <if test="maxAge !=null">
                and member_age &lt;=#{maxAge}<!--&lt; 是<号的意思-->
            </if>
            <if test="City !=null">
            and member_city=#{City}<!--&lt; 是<号的意思-->
            </if>
            </trim>
    </select>

创建测试类测试

public class MemberDAOTest {
    @Test
    public void testSearchMember() {
//            HashMap<String,Object> params=new HashMap<String, Object>();
//            params.put("gender","女");
//            params.put("minAge",18);
//            params.put("maxAge",23);
//            params.put("city","武汉");

        //-------------------------------------------------------------
        //可以任意根据一个参数 动态查询
        MemberSearchCondition params2=new MemberSearchCondition();
            params2.setGenDer("女");
//            params2.setMinAge(18);
//            params2.setMaxAge(23);
//            params2.setCity("武汉");
        //======================================》》》》》》》》》》》》》》》》》》》

        MemberDAO memberDAO= MybatisUtils.getMapper(MemberDAO.class);
        List<Member> members=memberDAO.searchMember(params2);//参数可以换成params2
        for (Member m:members) {
            System.out.println(m);
        }
    }
}

12.2.7foreach方法

创建方法

  //查询多个城市
    public List<Member> searchMemberByCity(List<String> cities);

创建xml sql语句

 <resultMap id="memberMap" type="Member">
        <id column="member_id" property="memberId"/>
        <result column="member_nick" property="memberNick"/>
        <result column="member_gender" property="memberGender"/>
        <result column="member_age" property="memberAge"/>
        <result column="member_city" property="memberCity"/>
    </resultMap>
<!-- foreach collection="list" item="cityName" separator="," open="(" close=")"
        collection="list" 定一个是定义存放容器的类型
        item="cityName" 集合中每一个元素进行迭代时的别名,
        separator="," 因为要取到多个条件 所以要定义分隔符
        open="(" close=")" 因为要取到(武汉,宜昌)这样的格式 所以要设置开头结尾
        -->
    <select id="searchMemberByCity" resultMap="memberMap">
        select member_id,member_nick,member_gender,member_age,member_city from members where member_city in
        <foreach collection="list" item="cityName" separator="," open="(" close=")">
        #{cityName}
        </foreach>
    </select>

创建测试类

    @Test
    public void searchMemberByCity() {
            List<String> cities=new ArrayList<String>();
            cities.add("武汉");
            cities.add("宜昌");
        MemberDAO memberDAO= MybatisUtils.getMapper(MemberDAO.class);
        List<Member> members=memberDAO.searchMemberByCity(cities);
        for (Member m:members) {
            System.out.println(m);
        }
    }

十三.模糊查询

13.1.1创建DAO方法 方法一

public interface MemberDAO{
    //根据昵称查询用户信息-模糊查询
    public List<Member> searchMemberByNick(HashMap params);
}

创建xml映射文件

    <resultMap id="memberMap" type="Member">
        <id column="member_id" property="memberId"/>
        <result column="member_nick" property="memberNick"/>
        <result column="member_gender" property="memberGender"/>
        <result column="member_age" property="memberAge"/>
        <result column="member_city" property="memberCity"/>
    </resultMap>
	<select id="searchMemberByNick" resultMap="memberMap">
        select member_id,member_nick,member_gender,member_age,member_city from members where member_nick like '%${keyWord}%'
    </select>
    <!--${key}表示获取参数,先获取参数的值拼接到SQL语句中,再编译执行sql语句 可能引起SQL注入阿您
-->
    <!--#{key}表示获取参数,先完成SQL编译(预编译),预编译之后再将获取的参数设置到sql中 可以避免SQL注入问题
-->

测试方法

  @Test
    public  void testsearchMemberByNick(){
        MemberDAO memberDAO=MybatisUtils.getMapper(MemberDAO.class);
        HashMap<String,Object> params=new HashMap<>();
        params.put("keyWord","花");
        List<Member> members=memberDAO.searchMemberByNick(params);
        for (Member b:members) {
            System.out.println(b);
        }

    }

方法二

不使用hashmap 用String参数

public interface MemberDAO{
    //根据昵称查询用户信息-模糊查询
    //模糊查询需要使用${科}取值,与sql进行拼接
    //在使用${}时,即使只有一个参数也需要使用@Param注解声明参数的key(非String对象参数可以不用声明)
    public List<Member> searchMemberByNick(@Param("keyWord") String params);
}

创建xml映射文件

<!--如果参数时String类型,需要parameterType声明参数类型-->
    <select id="searchMemberByNick" parameterType="java.lang.String" resultMap="memberMap">
        select member_id,member_nick,member_gender,member_age,member_city from members where member_nick like '%${keyWord}%'
    </select>
    <!--${key}表示获取参数,先获取参数的值拼接到SQL语句中,再编译执行sql语句 可能引起SQL注入问题
-->
    <!--#{key}表示获取参数,先完成SQL编译(预编译),预编译之后再将获取的参数设置到sql中 可以避免SQL注入问题
-->

测试方法

    @Test
    public  void testsearchMemberByNick(){
        MemberDAO memberDAO=MybatisUtils.getMapper(MemberDAO.class);

        List<Member> members=memberDAO.searchMemberByNick("花");
        for (Member b:members) {
            System.out.println(b);
        }
    }

13.2#{}和${}的区别

<!--${key}表示获取参数,先获取参数的值拼接到SQL语句中,再编译执行sql语句 可能引起SQL注入问题
-->
    <!--#{key}表示获取参数,先完成SQL编译(预编译),预编译之后再将获取的参数设置到sql中 可以避免SQL注入问题
-->

十四、MyBatis日志配置

MyBatis做为一个封装好的ORM框架,其运行过程我们没办法跟踪,为了让开发者了解MBatis执行流程及每个执行步骤所完成的工作,MvBatis框架本身继承了log4i日志框架,对运行的过程进行跟踪记录。我们只需要对 MyBatis进行相关的日志配置,就可以看到MyBatis运行过程中的日志信息

14.添加日志框架依赖

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

14.2添加日志配置文件

  • 在resources目录下创建名为log4j.properties文件

  • 在log4j.properties文件配置日志输出 的方式

#声明日志的输出级别及输出方式
log4j.rootLogger=DEBUG,stdout
#MyBatis Logging configuration. . .
log4j.logger.org.mybatis.example.BlogMapper=TRACE
 #Console output. . .
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
#定义日志的打印格式      %t表示线程名称 %5p 日志级别 %msg日志信息
loh4j.appender.stdout.layout.ConversionPattern=[%t] %5p - %msg \:%n%m

14.3日志信息的级别

十五.配置数据库连接池

MyBatis做为一个ORM框架,在进行数据库操作时是需要和数据库连接连接的,MxBatis支持基于数据库连接池的连接创建方式。

当我们配置MvBatis数据源时,只要配置了dataSaurce标签的type属性值为POOLED时,就可以使用MMBatis内置的连接池管理连接。

如果我们想要使用第三方的数据库连接池,则需进行自定义配置。

15.1常见的连接池

  • DBCP

  • C3PO

  • Druid 性能也比较好,提供了比较便捷的监控

  • Hikari 性能最好

15.2添加Durid依赖

<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.5</version>
        </dependency>

15.3创建Druid连接池工厂

public class DruidDataSourceFactory extends PooledDataSourceFactory {
    public DruidDataSourceFactory(){
        this.dataSource=new DruidDataSource();
    }
}

15.4将MyBatis的连接池替换为Druid

 <environments default="mysql">
        <environment id="mysql">
<!--            事务管理 jdbc-->
            <transactionManager type="JDBC"></transactionManager>
<!--           数据库的连接池-->
<!--            POOLED使用MyBatis内置的连接池实现-->
<!--             mybatis需要一个连接池工厂,这个工厂可以产生数据库连接池PooledDataSourceFactory -->

            <dataSource type="com.hr.utils.DruidDataSourceFactory">
                <property name="driverClass" value="${mysql_driver}"/>
                <property name="jdbcUrl" value="${mysql_url}"/>
                <property name="username" value="${mysql_username}"/>
                <property name="password" value="${mysql_password}"/>
            </dataSource>
        </environment>
    </environments>

十六、Mybatis缓存

MvBatis是基于JDBC的封装,使数据库操作更加便捷;MyBatis除了对JDBC操作步骤进行封装之外也对其性能进行了优化: 1·在MvBatis引入缓存机制,用于提升MyBatis的检索效率 2.在MvBatis引入延迟加载机制,用于减少对数据库不必要的访问

16.1一级缓存机制的原理

16.2Mybatis缓存

Mybatis缓存分为一级缓存和二级缓存

16.2.1一级缓存

一级缓存也叫做SqlSession级缓存,为每个SalSession单独分配的缓存内存,无需手动开启可直接使用;多个SalSession的缓存是不共享的。 特性: 1.如果多次查询使用的是同一个SalSession对象,则第一次查询之后数据会存放到缓存,后续的查询则直接访问缓存中存储的数据

2.如果第一次查询完成之后,对查询出的对象进行修改(此修改会影响到缓存),第二次查询会直接访问缓存,造成第二次查询的结果与数据库不一致; 3.当我们进行在查询时想要跳过缓存直接查询数据库,则可以通过sglSession.clearCache(;来清除当前SqlSession的缓存

4.如果第一次查询之后第二查询之前,使用当前的salsession执行了修改操作,此修改操作会使第一次查询并缓存的数据失效,因此第二次查询会再次访问数据库。

16.2.2两次查询不一致问题

16.2.3二级缓存

二级缓存 也称之为SqlSessionFactory级缓存,通过同一个factory对象获取的Sqlsession可以共享二级缓存

应用服务器中SqlSessionFactory是单例的,因此我们二级缓存可以实现全局共享

特性:

1.二级缓存默认没有开启,需要在mybatis-config.xml中的settings标签开启 2.二级缓存只能缓存实现序列化接的对象

  • 在Mybatis-config.xml 开启二级缓存

 <settings>
        <setting name="cachEnabled" value="true"/>
    </settings>
  • 在需要使用二级缓存的Mapper文件中配置cache标签使用功能二级缓存

    <cache/>

  • 被缓存的实体类实现序列化接口

  • public class Member implements Serializable {
        private  int memberId;
        private String memberNick;
        private  String memberGender;
        private int memberAge;
        private String memberCity;
        }

测试

1.多个SqLSession对象必须来自同一个SqlSessionFactory

  @Test
    public void testQueryMemberById(){

        SqlSessionFactory factory =MybatisUtils.SqlSessionFactory();
//        1.多个SqLSession对象必须来自同一个SqlSessionFactory
        SqlSession sqlSession1=factory.openSession(true);
        SqlSession sqlSession2=factory.openSession(true);
        System.out.println(sqlSession1==sqlSession2); //返回为false 不是同一个
        MemberDAO memberDAO1=sqlSession1.getMapper(MemberDAO.class);
        Member member1=memberDAO1.queryMemberById(1);
        System.out.println(member1);

        sqlSession1.commit();//第一次查询之后执行sqlSession1.commit(),会将当前salsession的查询结果缓存到二级缓存

        System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");

        MemberDAO memberDAO2=sqlSession2.getMapper(MemberDAO.class);
        Member member2=memberDAO1.queryMemberById(1);
        System.out.println(member2);
    }

16.3查询操作的缓存开关

<!--    useCache="false 表示查询的时候是否使用缓存"-->
    <select id="queryMemberById" resultMap="memberMap" useCache="false">
    select member_id,member_nick,member_gender,member_age,member_city from members where member_id=#{mid}
    </select>

十七.延迟加载(只在子查询中使用)

延迟加载─—如果在MxBatis开启了延迟加载,在执行了子查询(至少查询两次及以上)时,默认只执行第一次查询,当用到子查询的查询结果时,才会触发子查询的执行;如果无需使用子查询结果,则子查询不会执行。

16.1创建实体类

ClazzStudent

16.2创建DAO类方法

ClassDAOStudentDAO

16.3创建子链接操做

ClassMapper.xmlStudentMapper.xml

16.4创建测试类 编写方法

package com.hr.Dao;

import com.hr.pojo.Clazz;
import com.hr.utils.MybatisUtils;
import org.junit.Test;

import static org.junit.Assert.*;

public class ClassDAOTest {
//延迟加载测试类
    @Test
    public void queryClassById() {
        ClassDAO classDAO= MybatisUtils.getMapper(ClassDAO.class);
        Clazz clazz=classDAO.queryClassById(1);
        System.out.println(clazz.getClassName());

        MybatisUtils.close();//当地一次查询之后关闭SqlSession 下面查询会自动重新执行
        System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ");

        System.out.println(clazz.getStus());
    }
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MyBatis是一种开源持久层框架,它可以帮助我们实现将Java对象映射到关系型数据库中的数据。下面是MyBatis详细笔记: 1. MyBatis的介绍 MyBatis是一种Java持久层框架,它可以帮助我们实现将Java对象映射到关系型数据库中的数据。MyBatis是一种比较灵活的框架,它不会对应用程序中的Java对象进行任何修改,而是直接使用对象。 2. MyBatis的核心组件 MyBatis的核心组件包括SqlSessionFactory、SqlSession、Mapper和XML映射文件。 SqlSessionFactory:SqlSessionFactory是MyBatis的核心组件之一,它负责创建SqlSession对象。它是线程安全的,因此可以被多个线程共享。 SqlSession:SqlSession是MyBatis的另一个核心组件,它提供了与数据库交互的方法,包括查询、插入、更新和删除。SqlSession是非线程安全的,因此每个线程都应该有自己的SqlSession对象。 Mapper:Mapper是一个接口,它定义了与数据库交互的方法。MyBatis可以根据Mapper接口创建代理对象,从而实现对数据库的访问。 XML映射文件:XML映射文件定义了Java对象与数据库表之间的映射关系。它包含了SQL语句、参数映射和结果映射等信息。 3. MyBatis的配置 MyBatis的配置文件包括以下几个部分: 数据源配置:数据源是与数据库建立连接的入口。MyBatis支持多种数据源,包括JDBC、C3P0和Druid等。 事务管理器配置:MyBatis支持事务管理,可以通过配置事务管理器来实现事务控制。 Mapper配置:Mapper接口与XML映射文件的配置。 4. MyBatis的使用 MyBatis的使用可以分为以下几个步骤: 创建SqlSessionFactory对象:SqlSessionFactory是MyBatis的核心组件之一,它负责创建SqlSession对象。 创建SqlSession对象:SqlSession是MyBatis的另一个核心组件,它提供了与数据库交互的方法,包括查询、插入、更新和删除。 执行SQL语句:MyBatis支持多种SQL语句,包括查询、插入、更新和删除等。 关闭SqlSession对象:SqlSession是非线程安全的,因此每个线程都应该有自己的SqlSession对象。使用完SqlSession对象后应该将其关闭,以释放资源。 5. MyBatis的优点 MyBatis具有以下优点: 灵活性:MyBatis是一种比较灵活的框架,它不会对应用程序中的Java对象进行任何修改,而是直接使用对象。 易于使用:MyBatis的使用非常容易,可以通过简单的配置文件和Mapper接口来实现对数据库的访问。 高效性:MyBatis的性能非常高,它可以通过SQL语句的优化来提高查询的效率。 6. MyBatis的缺点 MyBatis的缺点包括以下几个方面: 学习曲线较陡峭:MyBatis的学习曲线比较陡峭,需要一定的Java和SQL知识才能使用。 XML映射文件较复杂:MyBatis的XML映射文件比较复杂,需要深入了解其语法和规则才能编写正确的映射文件。 7. 总结 MyBatis是一种开源持久层框架,它可以帮助我们实现将Java对象映射到关系型数据库中的数据。MyBatis具有灵活、易于使用和高效等优点,但学习曲线较陡峭,XML映射文件较复杂。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值