使用Mybatis这篇就够了

2023-05-16

第一章 框架概述

1.1 三层架构

界面层: 和用户打交道的, 接收用户的请求参数, 显示处理结果的。(jsp ,html ,servlet)
业务逻辑层: 接收了界面层传递的数据,计算逻辑,调用数据库,获取数据
数据访问层: 就是访问数据库, 执行对数据的查询,修改,删除等等的。

  1. 三层对应的包
  • 界面层: controller包 (servlet)
  • 业务逻辑层: service 包(XXXService类)
  • 数据访问层: dao包(XXXDao类)
  1. 三层中类的交互
  • 用户使用界面层–> 业务逻辑层—>数据访问层(持久层)–>数据库(mysql)
  1. 三层对应的处理框架
  • 界面层—servlet—springmvc(框架)

  • 业务逻辑层—service类–spring(框架)

  • 数据访问层—dao类–mybatis(框架)

1.2 框架

框架是一个舞台, 一个模版

1.2.1 模版

  1. 规定了好一些条款,内容。
  2. 加入自己的东西

1.2.2 框架是一个模块

​ 1.框架中定义好了一些功能。这些功能是可用的。
​ 2.可以加入项目中自己的功能, 这些功能可以利用框架中写好的功能。

框架是一个软件,半成品的软件,定义好了一些基础功能, 需要加入你的功能就是完整的。
基础功能是可重复使用的,可升级的。

1.2.3 框架特点

  1. 框架一般不是全能的, 不能做所有事情
  2. 框架是针对某一个领域有效。 特长在某一个方面,比如mybatis做数据库操作强,但是他不能做其它的。
  3. 框架是一个软件

1.2.4 mybatis框架

mybatis框架,早期叫做ibatis, 代码在github。
mybatis是 MyBatis SQL Mapper Framework for Java (sql映射框架)
1)sql mapper :sql映射
可以把数据库表中的一行数据 映射为 一个java对象。
一行数据可以看做是一个java对象。操作这个对象,就相当于操作表中的数据

2) Data Access Objects(DAOs) : 数据访问 , 对数据库执行增删改查。

mybatis提供了哪些功能:

  1. 提供了创建Connection ,Statement, ResultSet的能力 ,不用开发人员创建这些对象了

  2. 提供了执行sql语句的能力, 不用你执行sql

  3. 提供了循环sql, 把sql的结果转为java对象, List集合的能力

    while (rs.next()) {
    	Student stu = new Student();
    	stu.setId(rs.getInt("id"));
    	stu.setName(rs.getString("name"));
    	stu.setAge(rs.getInt("age"));
    	//从数据库取出数据转为 Student 对象,封装到 List 集合
    	stuList.add(stu);
      }
    
  4. 提供了关闭资源的能力,不用你关闭Connection, Statement, ResultSet

开发人员做的是: 提供sql语句
最后是: 开发人员提供sql语句–mybatis处理sql—开发人员得到List集合或java对象(表中的数据)

1.3 JDBC 的缺陷

  1. 代码比较多,开发效率低
  2. 需要关注 Connection ,Statement, ResultSet 对象创建和销毁
  3. 对 ResultSet 查询的结果,需要自己封装为 List
  4. 重复的代码比较多些
  5. 业务代码和数据库的操作混在一起

1.4 总结

mybatis是一个sql映射框架,提供的数据库的操作能力。增强的JDBC,使用mybatis让开发人员集中精神写sql就可以了,不必关心Connection,Statement,ResultSet的创建,销毁,sql的执行。

第二章 快速入门

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gxdUVvTt-1648717794817)(C:\Users\Dell\AppData\Roaming\Typora\typora-user-images\image-20220329210206197.png)]

2.1 实现步骤

2.1.1 创建student数据库表

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g8CVNx60-1648717794819)(C:\Users\Dell\AppData\Roaming\Typora\typora-user-images\image-20220329210359947.png)]

2.1.2加入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.bjpowernode</groupId>
  <artifactId>ch01-hello-mybatis</artifactId>
  <version>1.0-SNAPSHOT</version>
  <!--<packaging>jar</packaging>-->
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <!--mybatis依赖-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.1</version>
    </dependency>
    <!--mysql驱动-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.9</version>
    </dependency>
  </dependencies>

  <build>
    <resources>
      <resource>
        <directory>src/main/java</directory><!--所在的目录-->
        <includes><!--包括目录下的.properties,.xml 文件都会扫描到-->
          <include>**/*.properties</include>
          <include>**/*.xml</include>
        </includes>
        <filtering>false</filtering>
      </resource>
    </resources>
  </build>
</project>

2.1.3创建实体类

package com.bjpowernode.domain;

//推荐和表名一样。容易记忆
public class Student {
    //定义属性, 目前要求是属性名和列名一样。
    private Integer id;
    private String name;
    private String email;
    private Integer age;

    public Integer getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", email='" + email + '\'' +
                ", age=" + age +
                '}';
    }
}

2.1.4创建持久层dao接口

package com.bjpowernode.dao;

import com.bjpowernode.domain.Student;

import java.util.List;

//接口操作student表
public interface StudentDao {

    //查询student表的所有的数据
    public List<Student> selectStudents();

    //插入方法
    //参数: student ,表示要插入到数据库的数据
    //返回值: int , 表示执行insert操作后的 影响数据库的行数
    public int insertStudent(Student student);
}

2.1.5创建mybatis的配置文件

叫做sql映射文件:写sql语句的。一般一个表一个sql映射文件

<?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.bjpowernode.dao.StudentDao">
    <!--
       select:表示查询操作。
       id: 你要执行的sql语法的唯一标识, mybatis会使用这个id的值来找到要执行的sql语句
           可以自定义,但是要求你使用接口中的方法名称。

       resultType:表示结果类型的, 是sql语句执行后得到ResultSet,遍历这个ResultSet得到java对象的类型。
          值写的类型的全限定名称
    -->
    <select id="selectStudents" resultType="com.bjpowernode.domain.Student" >
        select id,name,email,age from student order by id
    </select>

    <!--插入操作-->
    <insert id="insertStudent">
        insert into student values(#{id},#{name},#{email},#{age})
    </insert>
</mapper>
<!--
  sql映射文件(sql mapper): 写sql语句的, mybatis会执行这些sql
  1.指定约束文件
     <!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

    mybatis-3-mapper.dtd是约束文件的名称, 扩展名是dtd的。
  2.约束文件作用:  限制,检查在当前文件中出现的标签,属性必须符合mybatis的要求。

  3.mapper 是当前文件的根标签,必须的。
    namespace:叫做命名空间,唯一值的, 可以是自定义的字符串。
               要求你使用dao接口的全限定名称。

  4.在当前文件中,可以使用特定的标签,表示数据库的特定操作。
   <select>:表示执行查询,select语句
   <update>:表示更新数据库的操作, 就是在<update>标签中 写的是update sql语句
   <insert>:表示插入, 放的是insert语句
   <delete>:表示删除, 执行的delete语句
-->

2.1.6创建mybatis的主配置文件

一个项目就一个主配置文件。主配置文件提供了数据库的连接信息和sql映射文件的位置信息。

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

    <!--settings:控制mybatis全局行为-->
    <settings>
        <!--设置mybatis输出日志-->
        <setting name="logImpl" value="STDOUT_LOGGING" />
    </settings>

    <!--环境配置: 数据库的连接信息
        default:必须和某个environment的id值一样。
        告诉mybatis使用哪个数据库的连接信息。也就是访问哪个数据库
    -->
    <environments default="mydev">
        <!-- environment : 一个数据库信息的配置, 环境
             id:一个唯一值,自定义,表示环境的名称。
        -->
        <environment id="mydev">
            <!--
               transactionManager :mybatis的事务类型
                   type: JDBC(表示使用jdbc中的Connection对象的commit,rollback做事务处理)
            -->
            <transactionManager type="JDBC"/>
            <!--
               dataSource:表示数据源,连接数据库的
                  type:表示数据源的类型, POOLED表示使用连接池
            -->
            <dataSource type="POOLED">
                <!--
                   driver, user, username, password 是固定的,不能自定义。
                -->
                <!--数据库的驱动类名-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <!--连接数据库的url字符串-->
                <property name="url" value="jdbc:mysql://localhost:3306/springdb"/>
                <!--访问数据库的用户名-->
                <property name="username" value="root"/>
                <!--密码-->
                <property name="password" value="123456"/>
            </dataSource>
        </environment>


        <!--表示线上的数据库,是项目真实使用的库-->
        <environment id="online">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/onlinedb"/>
                <property name="username" value="root"/>
                <property name="password" value="fhwertwr"/>
            </dataSource>
        </environment>
    </environments>

    <!-- sql mapper(sql映射文件)的位置-->
    <mappers>
        <!--一个mapper标签指定一个文件的位置。
           从类路径开始的路径信息。  target/clasess(类路径)
        -->
        <mapper resource="com/bjpowernode/dao/StudentDao.xml"/>
        <!--<mapper resource="com/bjpowernode/dao/SchoolDao.xml" />-->
    </mappers>
</configuration>
<!--
   mybatis的主配置文件: 主要定义了数据库的配置信息, sql映射文件的位置

   1. 约束文件
   <!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

    mybatis-3-config.dtd:约束文件的名称

  2. configuration 根标签。
-->

2.1.7创建测试类

package com.bjpowernode;

import com.bjpowernode.domain.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.IOException;
import java.io.InputStream;
import java.util.List;

public class MyApp {

    public static void main(String[] args) throws IOException {
        //访问mybatis读取student数据
        //1.定义mybatis主配置文件的名称, 从类路径的根开始(target/clasess)
        String config="mybatis.xml";
        //2.读取这个config表示的文件
        InputStream in = Resources.getResourceAsStream(config);
        //3.创建了SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder  = new SqlSessionFactoryBuilder();
        //4.创建SqlSessionFactory对象
        SqlSessionFactory factory = builder.build(in);
        //5.获取SqlSession对象,从SqlSessionFactory中获取SqlSession
        SqlSession sqlSession = factory.openSession();
        //6.【重要】指定要执行的sql语句的标识。  sql映射文件中的namespace + "." + 标签的id值
        //String sqlId = "com.bjpowernode.dao.StudentDao" + "." + "selectStudents";
        String sqlId = "com.bjpowernode.dao.StudentDao.selectStudents";
        //7.【重要】执行sql语句,通过sqlId找到语句
        List<Student> studentList = sqlSession.selectList(sqlId);
        //8.输出结果
        //studentList.forEach( stu -> System.out.println(stu));
        for(Student stu : studentList){
            System.out.println("查询的学生="+stu);
        }
        //9.关闭SqlSession对象
        sqlSession.close();

    }

}

2.1.8配置日志功能

mybatis.xml 文件加入日志配置,可以在控制台输出执行的 sql 语句和参数

<!--settings:控制mybatis全局行为-->
<settings>
    <!--设置mybatis输出日志-->
    <setting name="logImpl" value="STDOUT_LOGGING" />
</settings>

效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qth5Fgrk-1648717794821)(C:\Users\Dell\AppData\Roaming\Typora\typora-user-images\image-20220329211740321.png)]

2.2 主要类的介绍

2.2.1Resources:

​ mybatis中的一个类, 负责读取主配置文件
​ InputStream in = Resources.getResourceAsStream(“mybatis.xml”);

2.2.2SqlSessionFactoryBuilder :

创建SqlSessionFactory对象,

​ SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
​ //创建SqlSessionFactory对象
​ SqlSessionFactory factory = builder.build(in);

2.2.3SqlSessionFactory :

重量级对象, 程序创建一个对象耗时比较长,使用资源比较多。在整个项目中,有一个就够用了。

SqlSessionFactory:接口 , 接口实现类: DefaultSqlSessionFactory
SqlSessionFactory作用: 获取SqlSession对象。SqlSession sqlSession = factory.openSession();

openSession()方法说明:
1. openSession() :无参数的, 获取是非自动提交事务的SqlSession对象

  1. openSession(boolean): openSession(true) 获取自动提交事务的SqlSession.
    openSession(false) 非自动提交事务的SqlSession对象

2.2.4SqlSession:

SqlSession接口 :定义了操作数据的方法 例如 selectOne() ,selectList() ,insert(),update(), delete(), commit(), rollback()
SqlSession接口的实现类DefaultSqlSession。

使用要求: SqlSession对象不是线程安全的,需要在方法内部使用, 在执行sql语句之前,使用openSession()获取SqlSession对象。
在执行完sql语句后,需要关闭它,执行SqlSession.close(). 这样能保证他的使用是线程安全的。

这里有一个问题,我们从始至终都没有用到Dao接口类,我们现在来用传统的Dao实现类来使用Dao接口

2.3mybatis使用传统dao开发方式

2.3.1创建持久层dao接口

package com.bjpowernode.dao;

import com.bjpowernode.domain.Student;

import java.util.List;

public interface StudentDao {

    List<Student> selectStudents();

    int insertStudent(Student student);
}

2.3.2创建dao接口实现类

package com.bjpowernode.dao.impl;

import com.bjpowernode.dao.StudentDao;
import com.bjpowernode.domain.Student;
import com.bjpowernode.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import java.util.List;

public class StudentDaoImpl implements StudentDao {
    @Override
    public List<Student> selectStudents() {
        //获取SqlSession对象
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        String sqlId="com.bjpowernode.dao.StudentDao.selectStudents";
        //执行sql语句, 使用SqlSession类的方法
        List<Student> students  = sqlSession.selectList(sqlId);
        //关闭
        sqlSession.close();
        return students;
    }
    @Override
    public int insertStudent(Student student) {
        //获取SqlSession对象
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        String sqlId="com.bjpowernode.dao.StudentDao.insertStudent";
        //执行sql语句, 使用SqlSession类的方法
        int nums = sqlSession.insert(sqlId,student);
        //提交事务
        sqlSession.commit();
        //关闭
        sqlSession.close();
        return nums;
    }
}

2.3.3测试类

package com.bjpowernode;

import com.bjpowernode.dao.StudentDao;
import com.bjpowernode.dao.impl.StudentDaoImpl;
import com.bjpowernode.domain.Student;
import org.junit.Test;

import java.util.List;

public class TestMyBatis {

    @Test
    public void testSelectStudents(){
        //com.bjpowernode.dao.StudentDao
        StudentDao dao  = new StudentDaoImpl();
        /**   实现原理:
         * List<Student> studentList  = dao.selectStudents(); 调用
         * 1.dao对象,类型是StudentDao,全限定名称是:com.bjpowernode.dao.StudentDao
         *   全限定名称 和 namespace 是一样的。
         *
         * 2.方法名称, selectStudents, 这个方法就是 mapper文件中的 id值 selectStudents
         *
         * 3.通过dao中方法的返回值也可以确定MyBatis要调用的SqlSession的方法
         *    如果返回值是List ,调用的是SqlSession.selectList()方法。
         *    如果返回值 int ,或是非List的, 看mapper文件中的 标签是<insert>,<update> 就会调用
         *    SqlSession的insert, update等方法
         *
         *  mybatis的动态代理: mybatis根据 dao的方法调用,获取执行sql语句的信息。
         *     mybatis根据你的dao接口,创建出一个dao接口的实现类, 并创建这个类的对象。
         *     完成SqlSession调用方法, 访问数据库。
         *
         */
        List<Student> studentList  = dao.selectStudents();
        for(Student stu:studentList){
            System.out.println(stu);
        }
    }

    @Test
    public void testInsertStudent(){
        StudentDao dao  = new StudentDaoImpl();
        Student student = new Student();
        student.setId(1005);
        student.setName("盾山");
        student.setEmail("dunshan@qq.com");
        int nums = dao.insertStudent(student);
        System.out.println("添加对象的数量:"+nums);
    }

}

2.2.4工具类

package com.bjpowernode.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class MyBatisUtils {

    private  static  SqlSessionFactory factory = null;
    static {
        String config="mybatis.xml"; // 需要和你的项目中的文件名一样
        try {
            InputStream in = Resources.getResourceAsStream(config);
            //创建SqlSessionFactory对象,使用SqlSessionFactoryBuild
            factory = new SqlSessionFactoryBuilder().build(in);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    //获取SqlSession的方法
    public static SqlSession getSqlSession() {
        SqlSession sqlSession  = null;
        if( factory != null){
            sqlSession = factory.openSession();// 非自动提交事务
        }
        return sqlSession;
    }
}

2.4 传统 Dao 开发方式的分析

​ 在前面例子中自定义 Dao 接口实现类时发现一个问题:Dao 的实现类其实并没有干什么实质性的工 作,它仅仅就是通过 SqlSession 的相关 API 定位到映射文件 mapper 中相应 id 的 SQL 语句,真正对 DB 进 行操作的工作其实是由框架通过 mapper 中的 SQL 完成的。
​ 所以,MyBatis 框架就抛开了 Dao 的实现类,直接定位到映射文件 mapper 中的相应 SQL 语句,对 DB 进行操作。这种对 Dao 的实现方式称为 Mapper 的动态代理方式。
​ Mapper 动态代理方式无需程序员实现 Dao 接口。接口是由 MyBatis 结合映射文件自动生成的动态代 理实现的。

第三章 Mybatis框架Dao代理

3.1 实现方式

3.1.1去掉Dao接口实现类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FKiHu7id-1648717794822)(C:\Users\Dell\AppData\Roaming\Typora\typora-user-images\image-20220329214821252.png)]

由于用到了动态代理,所以,我们不需要创建Dao的接口实现类,直接交给代理来生成Dao的接口实现类。

动态代理: 使用SqlSession.getMapper(dao接口.class) 获取这个dao接口的对象

3.1.2 getMapper获取代理对象

package com.bjpowernode;

import com.bjpowernode.dao.StudentDao;
import com.bjpowernode.domain.Student;
import com.bjpowernode.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.Test;

import java.util.List;

public class TestMyBatis {

    @Test
    public void testSelectStudents(){
        /**
         * 使用mybatis的动态代理机制, 使用SqlSession.getMapper(dao接口)
         * getMapper能获取dao接口对于的实现类对象。
         */
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao dao  =  sqlSession.getMapper(StudentDao.class);

        //com.sun.proxy.$Proxy2 : jdk的动态代理
        System.out.println("dao="+dao.getClass().getName());
        //调用dao的方法, 执行数据库的操作
        List<Student> students = dao.selectStudents();
        for(Student stu: students){
            System.out.println("学生="+stu);
        }
    }

    @Test
    public void testInsertStudent(){
        SqlSession sqlSession  = MyBatisUtils.getSqlSession();
        StudentDao dao  =  sqlSession.getMapper(StudentDao.class);

        Student student = new Student();
        student.setId(1007);
        student.setName("李飞");
        student.setEmail("dunshan@qq.com");
        student.setAge(28);
        int nums = dao.insertStudent(student);
        sqlSession.commit();
        System.out.println("添加对象的数量:"+nums);
    }

}

3.2 深入理解参数

3.2.1 parameterType

parameterType : dao接口中方法参数的数据类型。parameterType它的值是java的数据类型全限定名称或者是mybatis定义的别名
例如:parameterType=“java.lang.Integer”
parameterType=“int”

intjava.lang.Integer 
	 hashmap 或 java.util.HashMap 
	 list 或 java.util.ArrayList 
	 student 或 com.bjpowernode.domain.Student

注意:默认值为未设置(unset)。接口中方法的参数从 java 代码传入到 mapper 文件的 sql 语句。
parameterType不是强制的,mybatis通过反射机制能够发 现接口参数的数类型。 所以可以没有。 一般我们也不写。

当传递的参数只有一个的时候:多个则不能使用这个属性

<select id="selectStudentById" parameterType="int" resultType="com.bjpowernode.domain.Student">
    select id,name, email,age from student where id=${studentId}
</select>

3.2.2 MyBatis 传递参数

1.一个简单参数

Dao 接口中方法的参数只有一个简单类型(java 基本类型和 String),占位符 #{ 任意字符 },和方法的参数名无关。与传入的对象无关,与传入的值有关。

单个参数传递给sql语句时不需要用命名参数,否则就需要使用命名参数。

接口:

/**
 * 一个简单类型的参数:
 *   简单类型: mybatis把java的基本数据类型和String都叫简单类型。
 *  在mapper文件获取简单类型的一个参数的值,使用 #{任意字符}
 */
public Student selectStudentById(@Param("studentId") Integer id);

mapper:

<select id="selectStudentById" resultType="com.bjpowernode.domain.Student">
    select id,name, email,age from student where id=#{studentId}
</select>
#{studentId} , studentId 是自定义的变量名称,和方法参数名无关。

2.多个参数-使用@Param

当 Dao 接口方法多个参数,需要通过名称使用参数。在方法形参前面加入@Param(“自定义参数名”), mapper 文件使用#{自定义参数名}。

接口:

/**
 * 多个参数: 命名参数,在形参定义的前面加入 @Param("自定义参数名称")
 */
List<Student> selectMultiParam(@Param("myname") String name,
                               @Param("myage") Integer age);

mapper:

<!--多个参数,使用@Param命名-->
<select id="selectMultiParam" resultType="com.bjpowernode.domain.Student">
     select id,name, email,age from student where name=#{myname} or age=#{myage}
</select>

3.多个参数-使用对象

  • vo: value object , 放一些存储数据的类。比如说 提交请求参数, name ,age 现在想把name ,age 传给一个service 类。

  • vo: view object , 从servlet把数据返回给浏览器使用的类,表示显示结果的类。

  • pojo: 普通的有set, get方法的java类。 普通的java对象

     Servlet --- StudentService( addStudent( MyParam  param)  )
    
  • entity(domain域): 实体类, 和数据库中的表对应的类,

多个参数, 使用java对象的属性值,作为参数实际值
使用对象语法: #{属性名,javaType=类型名称,jdbcType=数据类型} 很少用。
javaType:指java中的属性数据类型。
jdbcType:在数据库中的数据类型。

例如: #{paramName,javaType=java.lang.String,jdbcType=VARCHAR}

我们使用常用的的简化方式:#{属性名} ,javaType, jdbcType的值mybatis反射能获取。不用提供。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KbqZTtdA-1648717794825)(C:\Users\Dell\AppData\Roaming\Typora\typora-user-images\image-20220329225921187.png)]

接口:

/**
 * 多个参数,使用java对象作为接口中方法的参数
 */
List<Student> selectMultiObject(QueryParam param);

mapper:

<select id="selectMultiObject" resultType="com.bjpowernode.domain.Student">
       select id,name, email,age from student where
        name=#{paramName,javaType=java.lang.String,jdbcType=VARCHAR}
        or age=#{paramAge,javaType=java.lang.Integer,jdbcType=INTEGER}
 </select>
<!-- =================以下是常用的格式================= -->
<select id="selectMultiObject" resultType="com.bjpowernode.domain.Student">
          select id,name, email,age from student where
           name=#{paramName}   or age=#{paramAge}
</select>

4.多个参数-按位置

参数位置从 0 开始, 引用参数语法 #{ arg 位置 } , 第一个参数是#{arg0}, 第二个是#{arg1}

接口:

/**
 * 多个参数-简单类型的,按位置传值,
 * mybatis.3.4之前,使用 #{0} ,#{1}
 * mybatis。3.4之后 ,使用 #{arg0} ,#{arg1}
 */
List<Student> selectMultiPosition( String name,Integer age);

mapper:

<!--多个参数使用位置-->
<select id="selectMultiPosition" resultType="com.bjpowernode.domain.Student">
      select id,name, email,age from student where
      name = #{arg0} or age=#{arg1}
</select>

5.多个参数-使用Map

Map 集合可以存储多个值,使用Map向 mapper 文件一次传入多个参数。Map 集合使用 String的 key, Object 类型的值存储参数。 mapper 文件使用 # { key } 引用参数值。

接口:

/**
 * 多个参数,使用Map存放多个值
 */
List<Student> selectMultiByMap(Map<String,Object> map);

mapper:

<!--多个参数,使用Map , 使用语法 #{map的key}-->
<select id="selectMultiByMap" resultType="com.bjpowernode.domain.Student">
      select id,name, email,age from student where
      name = #{myname} or age=#{age1}
</select>

6.#和$

#:占位符,告诉 mybatis 使用实际的参数值代替。并使用 PrepareStatement 对象执行 sql 语句, #{…}代替 sql 语句的“?”。这样做更安全可以防止sql注入,更迅速,通常也是首选做法。

$ 字符串替换,告诉 mybatis 使用 包 含 的 “ 字 符 串 ” 替 换 所 在 位 置 。 使 用 S t a t e m e n t 把 s q l 语 句 和 包含的“字符串”替换所在位置。使用 Statement 把 sql 语句和 使Statementsql{}的 内容连接起来。主要用在:替换表名列名,不同列排序等操作。可以替换表名或者列名, 你能确定数据是安全的。

<!--使用 ${}-->
<select id="selectUse$" resultType="com.bjpowernode.domain.Student">
     select * from student where name=${myname}
</select>
<!--使用 #{}-->
<select id="selectUse" resultType="com.bjpowernode.domain.Student">
     select * from student where name=#{myname}
</select>
在日志中看到select语句是有?占位符出现的,这就说明,mybatis底层是调用执行对象preparedStatement对象。
实际上一个#{}就是对应着在底层的JDBC中的一个?号占位符

转为 MyBatis 的执行是: String sql=” select id,name,email,age from student where id=?; 
PreparedStatement ps = conn.prepareStatement(sql); 
ps.setInt(1,1005);
  select id,name, email,age from student where id=#{studentId}
  # 的结果: select id,name, email,age from student where id=? 
  
  // String sql="select id,name, email,age from student where id=" + "1001";
  // 使用的Statement对象执行sql, 效率比PreparedStatement低。


  select id,name, email,age from student where id=${studentId}
  $ 的结果:select id,name, email,age from student where id=1001
#和 $区别
  1. #使用 ?在sql语句中做站位的, 使用PreparedStatement执行sql,效率高
  2. #能够避免sql注入,更安全。
  3. $不使用占位符,是字符串连接方式,使用Statement对象执行sql,效率低
  4. $有sql注入的风险,缺乏安全性。
  5. $:可以替换表名或者列名

3.2.3 别名的定义

定义自定义类型的别名

  1. 在mybatis主配置文件中定义,使定义别名
  2. 可以在resultType中使用自定义别名

定义在mybatis主配置文件当中:

<!--定义别名-->
    <typeAliases>
        <!--
            第一种方式:
            可以指定一个类型一个自定义别名
            type:自定义类型的全限定名称
            alias:别名(短小,容易记忆的)
        -->
        <typeAlias type="com.bjpowernode.domain.Student" alias="stu" />
        <typeAlias type="com.bjpowernode.vo.ViewStudent" alias="vstu" />
    </typeAliases>
  <typeAliases>
		<!--
          第二种方式
          <package> name是包名, 这个包中的所有类,类名就是别名(类名不区分大小写)
        -->
  
        <package name="com.bjpowernode.domain"/>
        <package name="com.bjpowernode.vo"/>
  </typeAliases>

3.3 封装Mybatis的输出结果

3.3.1 resultType

resultType结果类型, 指sql语句执行完毕后, 数据转为的java对象, java类型是任意的。resultType结果类型的它值 1. 类型的全限定名称 2. 类型的别名。

例如 java.lang.Integer别名是int。

处理方式:
1. mybatis执行sql语句, 然后mybatis调用类的无参数构造方法,创建对象。
2. mybatis把ResultSet指定列值付给同名的属性。

	<select id="selectMultiPosition" resultType="com.bjpowernode.domain.Student">
      select id,name, email,age from student
    </select>

	  对等的jdbc
	  ResultSet rs = executeQuery(" select id,name, email,age from student" )
	  while(rs.next()){
           Student  student = new Student();
				student.setId(rs.getInt("id"));
				student.setName(rs.getString("name"))
	  }

resultType: 执行 sql 得到 ResultSet 转换的类型,使用类型的完全限定名或别名。 注意如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身。resultType 和 resultMap,不能同时使用。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EwkfdDys-1648717794827)(C:\Users\Dell\AppData\Roaming\Typora\typora-user-images\image-20220330213158335.png)]

可以把resultType里面的值,可以看做是接口中方法的返回值

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-88vXlepi-1648717794828)(C:\Users\Dell\AppData\Roaming\Typora\typora-user-images\image-20220330155940294.png)]

1.简单类型

接口:int countStudent();

mapper:

<!--sql执行后返回一行一列-->
<!--<select id="countStudent" resultType="int">-->
<select id="countStudent" resultType="java.lang.Integer">
    select count(*) from student
</select>

2.对象类型

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fHoXwUL8-1648717794829)(C:\Users\Dell\AppData\Roaming\Typora\typora-user-images\image-20220330160233384.png)]

接口:

ViewStudent selectViewStudent(int id);

mapper:

<!--    返回的参数是对象类型-->
<select id="selectViewStudent" resultType="com.gz.vo.ViewStudent" >
    select id,name,email,age from student where id=#{id}
</select>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LzHw6uNx-1648717794830)(C:\Users\Dell\AppData\Roaming\Typora\typora-user-images\image-20220330214240452.png)]

3.Map

sql 的查询结果作为 Map 的 key 和 value。推荐使用 Map。 注意:Map 作为接口返回值,sql 语句的查询结果最多只能有一条记录。大于一条记录是错误。

//定义方法返回Map
Map<Object,Object> selectMapById(Integer id);
<!--返回Map
    1)列名是map的key, 列值是map的value
    2)只能最多返回一行记录。多余一行是错误
-->
<select id="selectMapById" resultType="java.util.HashMap">
    select id,name,email from student where id=#{stuid}
</select>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0j3PqWPK-1648717794832)(C:\Users\Dell\AppData\Roaming\Typora\typora-user-images\image-20220330214507029.png)]

3.3.2 resultMap

resultMap:结果映射, 指定列名和java对象的属性对应关系。
1)你自定义列值赋值给哪个属性
2)当你的列名和属性名不一样时,一定使用resultMap

​ resultMap和resultType不要一起用,二选一

resultMap 可以自定义 sql 的结果和 java 对象属性的映射关系。更灵活的把列值赋值给指定属性。 常用在列名和 java 对象属性名不一样的情况。

使用方式: 1.先定义 resultMap,指定列名和属性的对应关系。

​ 2.在中把 resultType 替换为 resultMap。

接口:

/*
*  使用resultMap定义映射关系
* */
List<Student> selectAllStudents();

mapper:

<!--使用resultMap
    1)先定义resultMap
    2)在select标签,使用resultMap来引用1定义的。
-->

<!--定义resultMap
    id:自定义名称,表示你定义的这个resultMap在<select>使用
    type:期望转为的 java 对象的全限定名称或别名 
-->
<resultMap id="studentMap" type="com.bjpowernode.domain.Student">
    <!--列名和java属性的关系-->
    <!--注解列,使用id标签
        column :列名
        property:java类型的属性名
    -->
    <id column="id" property="id" />
    <!--非主键列,使用result-->
    <result column="name" property="name" />
    <result column="email" property="email" />
    <result column="age" property="age" />

</resultMap>
<select id="selectAllStudents" resultMap="studentMap">
    select id,name, email , age from student
</select>

当数据库列名和 java 对象属性名不一样的情况下:

<resultMap id="myStudentMap" type="com.bjpowernode.domain.MyStudent">
    <!--列名和java属性的关系-->

    <id column="id" property="stuid" />
    <!--非主键列,使用result-->
    <result column="name" property="stuname" />
    <result column="email" property="stuemail" />
    <result column="age" property="stuage" />

</resultMap>
<!--列名和属性名不一样:第一种方式-->
<select id="selectMyStudent" resultMap="myStudentMap">

     select id,name, email , age from student
</select>

3.3.3 实体类属性名和列名不同的处理方式

步骤:

创建新的实体类 PrimaryStuden

package com.gz.entity;

public class PrimaryStudent {
    private Integer stuid;
    private String stuname;

    public PrimaryStudent() {
    }

    @Override
    public String toString() {
        return "PrimaryStudent{" +
                "stuid=" + stuid +
                ", stuname='" + stuname + '\'' +
                '}';
    }

    public Integer getStuid() {
        return stuid;
    }

    public void setStuid(Integer stuid) {
        this.stuid = stuid;
    }

    public String getStuname() {
        return stuname;
    }

    public void setStuname(String stuname) {
        this.stuname = stuname;
    }
}

1.使用列别名和resultType

接口方法

List<MyStudent> selectMyStudent();

mapper

<!--    第一种:当列名和java对象属性名不一样,使用resultMap-->
    <resultMap id="studentMap" type="Student">
        <id column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="email" property="email"/>
        <result column="age" property="age"/>
    </resultMap>
    <select id="studentResultMap" resultMap="studentMap">
        select id,name,email,age from student where id = #{id}
    </select>

2.使用resultMap

<!--    第二种:当列名和java对象属性名不一样,使用数据库别名-->
<select id="studentResultType" resultType="com.gz.entity.PrimaryStudent">
    select id as stuid,name as stuname,email,age from student where id = #{id}
</select>


<resultMap id="studentMap1" type="com.gz.entity.PrimaryStudent">
    <id column="id" property="stuid"/>
    <result column="name" property="stuname"/>
</resultMap>

3.使用数据库别名的方式

<!--    第三种:
1.当列名和java对象属性名不一样,使用数据库别名和实体类的属性名相同
2.resultType的默认原则是 同名的列值赋值给同名的属性, 使用列别名(java对象的属性名)-->
<select id="studentResultType" resultType="com.gz.entity.PrimaryStudent">
    select id as stuid,name as stuname,email,age from student where id = #{id}
</select>

3.4 模糊like

模糊查询的实现有两种方式:一是 java 代码中给查询数据加上“%” ;

​ 二是在 mapper 文件 sql 语句的条件位置加上“%”。

1.java 代码中提供要查询的 “%xxx%”

mapper

<!--第一种 like , java代码指定 like的内容-->
<select id="selectLikeOne" resultType="com.bjpowernode.domain.Student">
    select id,name,email,age from student where name like #{name}
</select>

测试类

@Test
public void testSelectLikeOne(){
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    StudentDao dao = sqlSession.getMapper(StudentDao.class);

    //准备好like的内容
    String name = "%李%";
    List<Student> students = dao.selectLikeOne(name);

    for(Student stu: students){
        System.out.println("#######学生="+stu);
    }
    sqlSession.close();
}

2.mapper 文件中使用 “%” #{xxx} “%”

mapper

<!--第二种方式:在mapper文件中拼接 like的内容-->
<select id="selectLikeTwo" resultType="com.bjpowernode.domain.Student">
    select id,name,email,age from student where name  like "%" #{name} "%"
</select>

测试类

@Test
public void testSelectLikeTwo(){
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    StudentDao dao = sqlSession.getMapper(StudentDao.class);

    //准备好like的内容
    String name = "张";
    List<Student> students = dao.selectLikeTwo(name);

    for(Student stu: students){
        System.out.println("*******学生="+stu);
    }
    sqlSession.close();
}

第四章 动态SQL

动态SQL: SQL的内容是变化的,可以根据条件获取到不同的sql语句。
主要是where部分发生变化。

动态 SQL,主要用于解决查询条件不确定的情况:在程序运行期间,根据用户提交的查询条件进行 查询。提交的查询条件不同,执行的 SQL 语句不同。若将每种可能的情况均逐一列出,对所有条件进行 排列组合,将会出现大量的 SQL 语句。此时,可使用动态 SQL 来解决这样的问题。

4.1 注意事项

  • 在 mapper 的动态 SQL 中若出现大于号(>)、小于号(<)、大于等于号(>=),小于等于号(<=)等 符号,最好将其转换为实体符号。否则,XML 可能会出现解析出错问题。
  • 在使用动态SQL的使用,接口接收的参数一定要使用对象的方式。

特别是对于小于号(<),在 XML 中是绝不能出现的。否则解析 mapper 文件会出错。所以我们要使用实体符号:

<小于& lt;
>大于& gt;
>=大于等于& gt;=
<=小于等于& lt;=

4.2动态SQL之< if >

对于该标签的执行,当 test 的值为 true 时,会将其包含的 SQL 片断拼接到其所在的 SQL 语句中。 语法:< if test=“条件”> sql 语句的部分 </ if>

接口:

//动态sql ,使用java对象作为参数
List<Student> selectStudentIf(Student student);

mapper:

<!-- if
     <if:test="使用参数java对象的属性值作为判断条件,语法 属性=XXX值">
	 (id > 0,1 = 1)是使用技巧,为了能够使语句正常执行,无论if能否执行都可以正常执行
-->
<select id="selectStudentIf" resultType="com.bjpowernode.domain.Student">
    select id,name, age, email from student
    where id > 0
    <if test="name !=null and name !='' ">
       and name = #{name}
    </if>
    <if test="age > 0">
        or age > #{age}
    </if>
</select>

4.3动态SQL之< where >

  • < if >标签的中存在一个比较麻烦的地方:需要在 where 后手工添加 1=1 的子句。因为,若 where 后 的所有条件均为 false,而 where 后若又没有 1=1 子句,则 SQL 中就会只剩下一个空的 where,SQL 出错。所以,在 where 后,需要添加永为真子句 1=1,以防止这种情况的发生。但当数据量很大时,会 严重影响查询效率。

  • 使用标签< where />,在有查询条件时,可以自动添加上 where 子句;没有查询条件时,不会添加 where 子句。需要注意的是,第一个< if />标签中的 SQL 片断,可以不包含 and。不过,写上 and 也不错, 系统会将多出的 and 去掉。但其它< if />>中 SQL 片断的 and,必须要求写上。否则 SQL 语句将拼接出错。

  • 语法:< where >其他动态SQL< where />

<!--
 where: <where> <if> <if>...</where>
-->
<select id="selectStudentWhere" resultType="com.bjpowernode.domain.Student">
    <include refid="studentSql" />
    <where>
        <if test="name !=null and name !='' ">
            name = #{name}
        </if>
        <if test="age > 0">
            or age > #{age}
        </if>
    </where>
</select>

4.4动态SQL之< foreach >

引入:当我们需要动态的给in命令里面添加参数时,我们要这样做

@Test
public void testfor(){
    List<Integer> list = new ArrayList<>();
    list.add(1001);
    list.add(1002);
    list.add(1003);

    //String sql="select * from student where id in (1001,1002,1003)";
    String sql="select * from student where id in";

    StringBuilder builder  = new StringBuilder("");
    int init=0;
    int len = list.size();

    //添加开始的 (
    builder.append("(");
    for(Integer i:list){
        builder.append(i).append(",");
    }
    builder.deleteCharAt(builder.length()-1);
    //循环结尾
    builder.append(")");
    sql = sql  + builder.toString();
    System.out.println("sql=="+sql);
}

特别的麻烦,所以我们有了< foreach >标签

在foreach中可以放循环的对象,也可以自定义小括号,用法灵活

  • 标签用于实现对于数组与集合的遍历。主要用在sql的in语句中。对其使用,需要注意:

➢ collection 表示要遍历的集合类型, list ,array 等。

➢ open、close、separator 为对遍历内容的 SQL 拼接。

  • 具体含义:

​ collection:表示接口中的方法参数的类型, 如果是数组使用array , 如果是list集合使用list
​ item:自定义的,表示数组和集合成员的变量
​ open:循环开始是的字符
​ close:循环结束时的字符
​ separator:集合成员之间的分隔符

  • 对应关系:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MhwesW6o-1648717794833)(C:\Users\Dell\AppData\Roaming\Typora\typora-user-images\image-20220331105311586.png)]

第一种用法:遍历 List<简单类型>

接口:

//foreach 用法 1
List<Student> selectForeachOne(List<Integer> idlist);

mapper:

<select id="selectForeachTwo" resultType="com.bjpowernode.domain.Student">
        select * from student where id in
        <foreach collection="list" item="stu" open="("  close=")" separator=",">
                 #{stu.id}
        </foreach>
</select>

测试:

@Test
public void testSelectForEach(){
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    StudentDao dao  =  sqlSession.getMapper(StudentDao.class);

    List<Integer> list = new ArrayList<>();
    list.add(1001);
    list.add(1002);
    list.add(1003);

    List<Student> students = dao.selectForeachOne(list);
    for(Student stu:students){
        System.out.println("foreach--one ==="+stu);
    }
}

第二种用法:遍历 List<对象类型>

接口:

//foreach 用法 2
List<Student> selectForeachTwo(List<Student> stulist);

mapper:

<select id="selectForeachTwo" resultType="com.bjpowernode.domain.Student">
    select * from student where id in (
    <foreach collection="list" item="stu" >
        #{stu.id},
    </foreach>
    -1 )
</select>

测试:

@Test
public void testSelectForTwo(){
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    StudentDao dao  =  sqlSession.getMapper(StudentDao.class);

    List<Student> stuList  = new ArrayList<>();
    Student s1 = new Student();
    s1.setId(1002);
    s1.setName("lisi");
    stuList.add(s1);

    s1 = new Student();
    s1.setId(1005);;
    s1.setName("zs");
    stuList.add(s1);

    List<Student> students = dao.selectForeachTwo(stuList);
    for(Student stu:students){
        System.out.println("foreach--two ==="+stu);
    }
}

4.5动态SQL之< sql >

< sql />标签用于定义 SQL 片断,以便其它 SQL 标签复用。而其它标签使用该 SQL 片断,需要使用< include />子标签。该< sql />标签可以定义 SQL 语句中的任何部分,所以< include />子标签可以放在SQL的任何位置。

<!--定义sql片段-->
<sql id="studentSql">
    select id,name, age, email from student
</sql>
<!--
 where: <where> <if> <if>...</where>
-->
<select id="selectStudentWhere" resultType="com.bjpowernode.domain.Student">
    <include refid="studentSql" />
    <where>
        <if test="name !=null and name !='' ">
            name = #{name}
        </if>
        <if test="age > 0">
            or age > #{age}
        </if>
    </where>
</select>

第五章 MyBatis配置文件

5.1 主配置文件

之前项目中使用的 mybatis.xml 是主配置文件。 主配置文件特点:

  1. 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" >
  1. 根元素,< configguration >
    主要包含内容:
    ➢ 定义别名
    ➢ 数据源
    ➢ mapper 文件

5.2 dataSource标签

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1eV2rnyF-1648717794834)(C:\Users\Dell\AppData\Roaming\Typora\typora-user-images\image-20220331164335393.png)]

Mybatis 将数据源分为三类:UNPOOLED 不使用连接池的数据源

​ POOLED 使用连接池的数据源

​ JNDI 使用 JNDI 实现的数据源

其中 UNPOOLED ,POOLED 数据源实现了 javax.sq.DataSource 接口, JNDI 和前面两个实现方式不同。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UchdfcpH-1648717794836)(C:\Users\Dell\AppData\Roaming\Typora\typora-user-images\image-20220331164518778.png)]

5.2.1 dataSource配置

<!--
   dataSource:表示数据源,java体系中,规定实现了javax.sql.DataSource接口的都是数据源。
              数据源表示Connection对象的。

   type:指定数据源的类型
      1)POOLED: 使用连接池, mybatis会创建PooledDataSource类
      2)UPOOLED: 不使用连接池, 在每次执行sql语句,先创建连接,执行sql,在关闭连接
                  mybatis会创建一个UnPooledDataSource,管理Connection对象的使用
      3)JNDI:java命名和目录服务(windows注册表)
-->
<dataSource type="POOLED">
    <!--数据库的驱动类名-->
    <property name="driver" value="${jdbc.driver}"/>
    <!--连接数据库的url字符串-->
    <property name="url" value="${jdbc.url}"/>
    <!--访问数据库的用户名-->
    <property name="username" value="${jdbc.user}"/>
    <!--密码-->
    <property name="password" value="${jdbc.passwd}"/>
</dataSource>

MyBatis 在初始化时,根据的 type 属性来创建相应类型的的数据源 DataSource,即:

  1. type=”POOLED”:MyBatis 会创建 PooledDataSource 实例
  2. type=”UNPOOLED” : MyBatis 会创建 UnpooledDataSource 实例
  3. type=”JNDI”:MyBatis 会从 JNDI 服务上查找 DataSource 实例,然后返回使用

5.3事务

5.3.1默认需要手动提交事务

  • Mybatis 框架是对 JDBC 的封装,所以 Mybatis 框架的事务控制方式,本身也是用 JDBC 的 Connection 对象的 commit(), rollback()
< transactionManager type="JDBC" />
  • Connection 对象的 setAutoCommit()方法来设置事务提交方式的。自动提交和手工提交、 该标签用于指定 MyBatis所使用的事务管理器。MyBatis 支持两种事务管理器类型:JDBC 与 MANAGED。

➢ JDBC:使用 JDBC 的事务管理机制。即,通过 Connection 的 commit()方法提交,通过 rollback()方法 回滚。但默认情况下,MyBatis 将自动提交功能关闭了,改为了手动提交。即程序中需要显式的对 事务进行提交或回滚。从日志的输出信息中可以看到。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8NV1r14p-1648717794837)(C:\Users\Dell\AppData\Roaming\Typora\typora-user-images\image-20220331165228331.png)]

➢ MANAGED:由容器来管理事务的整个生命周期(如 Spring 容器)。

5.3.2自动提交事务

设置自动提交的方式,factory 的 openSession() 分为有参数和无参数的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZwYBAlx6-1648717794839)(C:\Users\Dell\AppData\Roaming\Typora\typora-user-images\image-20220331165239668.png)]

有参数为 true,使用自动提交,可以修改 MyBatisUtil 的 getSqlSession()方法。

session = factory.openSession(false);

再执行 insert 操作,无需执行 session.commit(),事务是自动提交的

5.4 使用数据库属性配置文件

数据库的属性配置文件: 把数据库连接信息放到一个单独的文件中。 和mybatis主配置文件分开。目的是便于修改,保存,处理多个数据库的信息。MyBatis 主配置文件需要从这个属性文件中读取这些数据。

步骤:

5.4.1在 classpath 路径下,创建 properties 文件

在 resources 目录创建 jdbc.properties 文件,文件名称自定义。

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/springdb
jdbc.user=root
jdbc.passwd=123456

5.4.2 使用 properties 标签

修改主配置文件,文件开始位置加入:

<!--指定properties文件的位置,从类路径根开始找文件-->
<properties resource="jdbc.properties" />

5.4.3 使用key值

<dataSource type="POOLED">
    <!--数据库的驱动类名-->
    <property name="driver" value="${jdbc.driver}"/>
    <!--连接数据库的url字符串-->
    <property name="url" value="${jdbc.url}"/>
    <!--访问数据库的用户名-->
    <property name="username" value="${jdbc.user}"/>
    <!--密码-->
    <property name="password" value="${jdbc.passwd}"/>
</dataSource>

5.5 mappers(映射器)

5.5.1 < mapper resource=" " />

使用相对于类路径的资源,从 classpath 路径查找文件 例如:

<!-- sql mapper(sql映射文件)的位置-->
<mappers>
    <!--第一种方式:指定多个mapper文件-->
    <mapper resource="com/bjpowernode/dao/StudentDao.xml"/>
    <mapper resource="com/bjpowernode/dao/OrderDao.xml" />
</mappers>

5.5.2 < package name=" " />

指定包下的所有 Dao 接口

<mappers>
	<!--第二种方式: 使用包名
        name: xml文件(mapper文件)所在的包名, 这个包中所有xml文件一次都能加载给mybatis
        使用package的要求:
         1. mapper文件名称需要和接口名称一样, 区分大小写的一样
         2. mapper文件和dao接口需要在同一目录
    -->
    <package name="com.bjpowernode.dao"/>
    <package name="com.bjpowernode.dao2"/>
    <package name="com.bjpowernode.dao3"/>
</mappers>

注意:此种方法要求Dao 接口名称mapper 映射文件名称相同且在同一个目录中。< mapper >里面填的是路径,而< package >是包名

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用Mybatis这篇就够了 的相关文章

  • Image打包流程-Android10.0编译系统(四)

    摘要 xff1a 本节主要来进行Android10 0 Image打包流程 xff0c 理解system img是如何打包的 1 概述 前面我们讲完了Android10 0 编译的初始化和make的完整流程 xff0c 从make中我们看到

随机推荐

  • Ubuntu18.04安装踩坑与排错记录

    很早以前就想装Ubuntu玩玩了 xff0c 今天终于动手实现了这个想法 但过程并不顺利 xff0c 所以记录一下 对他人可能借鉴意义不大 xff0c 但对自己来说还是有记录价值的 机子是之前淘汰掉的华硕笔记本 xff08 14年买的 xf
  • Jupyter Notebook FileNotFoundError: [WinError 2] 系统找不到指定的文件

    问题描述 xff1a 通过Anaconda新创建环境 tfenv python 61 3 5 5 并依次安装tensorflow ipython xff0c jupyter xff0c matplotlib这三个包及其依赖包 然后在该环境下
  • 命令提示符(cmd)的一些简单用法

    命令提示符 xff08 cmd xff09 快捷键 xff1a win 43 r 切换位置 xff1a 盘名 xff1a 进入目录 xff1a cd 43 文件夹名 xff08 tab可以切换文件夹 xff09 只要路径写对cd可以访问多级
  • Java中,&&与&,||与|的区别

    1 1 逻辑运算符 amp amp xff08 短路与 xff09 xff0c amp 用法 xff1a amp amp 和 amp 都是表示与区别是 xff1a amp amp 若第一个条件不满足 xff0c 后面条件就不再判断 而 am
  • Java基础类(六):Collections工具类

    目录 1 Collections 1 1 排序操作 xff1a xff08 均为static方法 xff09 1 2 查找 替换 1 3 同步控制 1 4 返回不可变集合 1 Collections Collections 是一个操作 Se
  • Bash脚本:采用for循环重复执行某条指令100次

    1 新建一个脚本文件 直接vim for sh就可以 2 编辑脚本文件 bin bash for i 61 1 i lt 61 100 i 43 43 do test 想要重复执行的命令 xff09 done 3 将脚本文件变为可执行文件
  • Android.mk 和 CMakeLists.txt 的转换规则

    Android mk 和 CMakeLists txt 都是用来构建 Android 应用程序或库的工具 但是它们有不同的语法和规则 xff0c 所以将一个 Android mk 文件转换成一个 CMakeLists txt 文件需要一些注
  • EFI Shell 命令参考

    对于使用使用DOS的人来说 xff0c 会使用DOS命令是最基本的 xff0c 而在当今即将盛行的EFI BIOS来说 xff0c 就有了新的变化 xff0c 如何操作EFI Shell 呢 xff1f 至此我贴出了EFI Shell 的命
  • mysql出现提示错误10061的解决方法

    MySQL出现提示错误10061的解决方法 错误提示 xff1a 今天打开Navicat连接mysql突然提示 2003 Can t connect to MySQL server on localhost 10061 xff09 的错误提
  • 3分钟爬取全网10W+爆款,脚本无偿分享,零基础拿来直接就能用!

    市面上的新媒体资料都是过去时了 xff0c 只有最新的爆款文才是新媒体人的福音 xff01 三分钟爬取全网10W 43 爆款文 xff01 爬虫脚本无偿分享 xff0c 拿来就能直接用 xff0c 零基础也能用 xff01 需要的看图 xf
  • 使用Wake On Lan远程唤醒

    使用Wake On Lan远程唤醒 客厅里的那台htpc xff0c 在无下片任务的时候 xff0c 大部分时间里都在白白浪费电 主板是支持wake on lan的 xff0c 把它弄成可以远程控制会比较经济 首先要设置bios xff0c
  • .gitignore文件作用

    gitignore文件用于在将文件提交到git暂存区时 xff0c 指定将哪些文件排除 xff1b 1 gitignore文件基本用法 在 git文件所在的目录创建 gitignore 文件 文件内容如下 span class token
  • 《计算机应用基础》形考作业及答案

    国家开放大学 计算机应用基础 形考作业 及 答案 题目1 nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp 兔子bu蹬鹰 在Word 2010中编辑文本时 编辑
  • php操作redis代码

    lt php Redis缓存操作 64 author hxm 64 version 1 0 64 since 2015 05 04 class RCache extends Object implements CacheFace priva
  • C++实现归并排序

    C 43 43 实现归并排序 span class token comment span span class token comment main cpp span span class token comment MergeSort s
  • LinuxNote 第二章 新手必须掌握的Linux命令

    目录 第二章 新手必须掌握的Linux命令2 1 Shell2 2 命令格式及帮助命令 man2 2 1 命令格式2 2 2 帮助命令 man 2 3 常用的系统工作命令2 3 1 echo2 3 2 date2 3 3 reboot2 3
  • Linux PXE无盘工作站

    关于PXE无盘工作站系统的简介 PXE无盘工作站系统是指由一台或多台 系统服务器 和多台 PXE客户端 无盘工作站 通过 交换机 相连组成的局域网系统 xff08 图1 xff1a 无盘工作站系统部署拓扑图 xff09 系统服务器 xff1
  • 环形缓冲区的实现原理

    http blog chinaunix net uid 7491192 id 2051200 html 在通信程序中 xff0c 经常使用环形缓冲区作为数据结构来存放通信中发送和接收的数据 环形缓冲区是一个先进先出的循环缓冲区 xff0c
  • 计算任意二叉树T中其数据域大于等于x的结点个数并返回该值

    span class token macro property span class token directive keyword include span span class token string lt stdio h gt sp
  • 使用Mybatis这篇就够了

    第一章 框架概述 1 1 三层架构 界面层 xff1a 和用户打交道的 xff0c 接收用户的请求参数 xff0c 显示处理结果的 xff08 jsp xff0c html xff0c servlet xff09 业务逻辑层 xff1a 接