MyBatis

MyBatis

author:あさひ
小煦

软件下载地址:https://github.com/mybatis/mybatis-3/releases

GitHub地址:https://github.com/mybatis/mybatis-3

官方文档参考地址:https://mybatis.org/mybatis-3/zh/getting-started.html

一、框架概述

三层架构

界面层(User Interface layer): 和用户打交道的, 接收用户的请求参数, 显示处理结果的。(jsp ,html ,servlet)

controller包 (servlet)

业务逻辑层(Business Logic Layer): 接收了界面层传递的数据,计算逻辑,调用数据库,获取数据

service 包(XXXService类)

数据访问层(Data access layer): 就是访问数据库, 执行对数据的查询,修改,删除等等的。

dao包(XXXDao类)

三层交互顺序为: 用户使用界面层--> 业务逻辑层--->数据访问层(持久层)-->数据库(mysql)

三层架构对应的处理框架

  • 界面层---servlet---springmvc(框架)
  • 业务逻辑层---service类--spring(框架)
  • 数据访问层---dao类--mybatis(框架)

框架

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

模版:

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

框架是一个模块

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

框架特点

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

JDBC的缺陷

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

二、MyBatis框架入门

MyBatis SQL Mapper Framework for Java

SQL Mapper:可以把数据库表中的一行数据 映射为 一个java对象。一行数据可以看做是一个java对象。操作这个对象,就相当于操作表中的数据

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

MyBatis是一个优秀的基于java的持久层框架,内部封装了jdbc,开发者只需要关注sql语句本身,而不需要处理加载驱动、创建连接、创建statement、关闭连接,资源等繁杂的过程。MyBatis通过xml或注解两种方式将要执行的各种sql语句配置起来,并通过java对象和sql 的动态参数进行映射生成最终执行的sql 语句,最后由mybatis 框架执行sql 并将结果映射为java 对象并返回。

MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)
当前,最新版本是MyBatis 3.5.6,发布时间:2020年7月10日,上午4:57。

GitHub地址:https://github.com/mybatis/mybatis-3

官方文档参考地址:https://mybatis.org/mybatis-3/zh/getting-started.html

mybatis提供的功能

  • 提供了创建Connection ,Statement, ResultSet的能力 ,不用开发人员创建这些对象了
  • 提供了执行sql语句的能力, 不用你执行sql
  • 提供了循环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);
	  }
  • 提供了关闭资源的能力,不用你关闭Connection, Statement, ResultSet

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

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

入门第一个示例

要求:

1、新建student表

2、创建一个maven项目,加入maven的mybatis坐标,mysql驱动的坐标

3、创建实体类,Student--保存表中的一行数据

4、创建持久层的DAO接口,定义操作数据库的方法

5、创建一个mybatis使用的配置文件
  叫做sql映射文件,写SQL语句的一般一个表一个sql映射文件。这个文件是XML文件。
  文件在接口所在的目录中。
  文件名称和接口保持一致。
  
6、创建一个mybatis的主配置文件:
	一个项目中就一个主配置文件
	主配置文件提供了数据库连接信息和sql映射文件的位置信息
	
7、创建使用mybatis类,通过mybatis访问数据库

代码实现

  • 按照要求在Navicat中测试数据库新建一个student表。

image-20210202114415647

  • 加入maven的mybatis坐标,mysql驱动的坐标
<!--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.48</version>
    </dependency>
  • 创建实体类,Student--保存表中的一行数据

实体类

package org.hanxu.domain;

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

    public Student(Integer id, String name, String email, Integer age) {
        this.id = id;
        this.name = name;
        this.email = email;
        this.age = age;

    }

    public Student() {
    }

    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 +
                '}';
    }
}

编写DAO接口类

package org.hanxu.dao;

import org.hanxu.domain.Student;

import java.util.List;

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

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

接口类同目录的XML文件(SQL映射)

StudentDao.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!--sql映射文件(sql mapper),写sql语句的,mybatis会执行这些sql
    指定约束文件
    mybatis-3-mapper.dtd是约束文件的名称,扩展名是dtd的。
    约束文件的作用
    限制、检查当前文件中出现的标签和属性,必须符合mybatis的要求
-->
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!--
    mapper  是当前文件的根标签,必须的
    namespace   叫做命名空间,唯一值,可以是自定义的字符串
                要求你使用dao接口的全限定名称。
    在当前文件中,可以使用特定的标签,表示数据库的特定操作
    <select>:表示执行查询
    <update>:表示更新数据库的操作,就是在<update>标签中写的是update sql语句
    <insert>:表示插入,放的是insert语句
    <delete>:表示删除,执行delete语句
-->
<mapper namespace="org.hanxu.dao.StudentDao">
    <select id="selectBlog" resultType="Blog">
    select * from blog where id = #{id}
    </select>

    <!--
        select 表示查询操作
        id  你要执行sql语句的唯一标识,mybatis会使用这个id的值,来找到要执行的sql语句
            可以自定义,但是要求你使用接口中的方法名

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

  <!--
  sql映射文件:写sql语句的,mybatis会执行这些sql语句
  -->
</mapper>

mybatis主配置文件链接数据库

文件位置resource根目录下,文件名称自定义如:mybatis.xml

官网中的示例代码为:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <property name="driver" value="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
      </dataSource>
    </environment>
  </environments>
  <mappers>
    <mapper resource="org/mybatis/example/BlogMapper.xml"/>
  </mappers>
</configuration>

我自己的配置

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="mydev">
        <environment id="mydev">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/test?useSSL=false"/>
                <property name="username" value="root"/>
                <property name="password" value="hanxu"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="org/hanxu/dao/StudentDao.xml"/>
    </mappers>
</configuration>

在pom.xml中加上maven指定资源位置

<build>
    <resources>
      <resource>
        <directory>src/main/java</directory><!--所在的目录-->
        <includes><!--包括目录下的.properties,.xml 文件都会扫描到-->
          <include>**/*.properties</include>
          <include>**/*.xml</include>
        </includes>
        <!--filtering 选项 false 不启用过滤器, *.property 已经起到过滤的作用了 -->
        <filtering>false</filtering>
      </resource>
    </resources>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.1</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
    </plugins>
</build>

主程序测试

package org.hanxu;


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

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/class)
        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 = "org.hanxu.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();


    }


}

/*执行结果:
查询的学生=Student{id=1001, name='李四', email='lisi@qq.com', age=20}
查询的学生=Student{id=1002, name='张三', email='zhangsan@qq.com', age=28}
*/

插入功能测试

DAO接口加入插入方法
package org.hanxu.dao;

import org.hanxu.domain.Student;

import java.util.List;

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

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

    //插入方法
    //参数:
    // student 表示要插入的数据
    // int 表示执行insert操作后的影响数据库的行数
    public int insertStudents(Student student);
}
mapper映射添加插入sql语句
<insert id="insertStudents">
        insert into student value(#{id},#{name},#{email},#{age})
</insert>
测试代码
package org.hanxu;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.hanxu.domain.Student;
import org.junit.Test;

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


public class TestMyBatis {
    //测试方法,测试功能
    @Test
    public void  testInsert() throws IOException {
        //访问mybatis,读取student数据
        //1、定义mybatis主配置文件的名称,从类路径根开始(target/classes)
        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 = "org.hanxu.dao.StudentDao.insertStudents";

        //7、执行sql语句,通过sqlId找到语句
        Student student = new Student(1004,"李飞","lifei@163.com",23);
        int num = sqlSession.insert(sqlId,student);
        //mybatis默认不是自动提交事务的,所以在insert,update,delete后要手动提交事务
        sqlSession.commit();

        //8、输出结果
        System.out.println("执行操作行数:" +num+"行");

        sqlSession.close();
    }

}

设置日志

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

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

总结步骤

  • 作用

    • 增强的jdbc,访问数据库,执行增删改查
  • 基本步骤

    • 加入maven依赖

      • <!--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>
        
    • 创建Dao接口

      • 定义了你操作数据的方法
    • 创建mapper文件,也叫做sql映射文件:写sql语句的,和接口中方法对应的sqly语句

    • 创建mybatis的一个主配置文件

      • 链接数据库
      • 指定mapper文件的位置
    • 使用mybatis对象SqlSession,通过他的方法执行sql语句

避免踩坑

在测试时发现,maven编译的时候资源文件不一定会拷贝到target\classes目录下,首先检查pom.xml中是否添加了资源位置

 <resources>
      <resource>
        <directory>src/main/java</directory><!--所在的目录-->
        <includes><!--包括目录下的.properties,.xml 文件都会扫描到-->
          <include>**/*.properties</include>
          <include>**/*.xml</include>
        </includes>
        <!--filtering 选项 false 不启用过滤器, *.property 已经起到过滤的作用了 -->
        <filtering>false</filtering>
      </resource>
    </resources>

资源目录下的文件,默认idea会拷贝到target\classe,如果没有拷贝,需要检查资源文件夹是否make as resource,如果还是不能拷贝,点击菜单栏

---Build--Rebuild Project

然后再重新编译执行,一般都可以解决。或者直接清除idea缓存:--File--Invilidate caches/Restart.

我的暴力解决办法就是再次添加资源位置!!!如果还不行,那就再暴力一点,勤快一点,直接手动拷贝吧~哎

<resource>
  <directory>src/main/resources</directory><!--所在的目录-->
  <includes><!--包括目录下的.properties,.xml 文件都会扫描到-->
    <include>**/*.properties</include>
    <include>**/*.xml</include>
  </includes>
  <!--filtering 选项 false 不启用过滤器, *.property 已经起到过滤的作用了 -->
  <filtering>false</filtering>
</resource>

三、主要类的介绍

Resources: mybatis中的一个类, 负责读取主配置文件

InputStream in = Resources.getResourceAsStream("mybatis.xml");

SqlSessionFactoryBuilder : 创建SqlSessionFactory对象

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

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

SqlSessionFactory:接口 , 接口实现类: DefaultSqlSessionFactory

SqlSessionFactory作用: 获取SqlSession对象。SqlSession sqlSession = factory.openSession();

openSession()方法说明

  • openSession() :无参数的, 获取是非自动提交事务的SqlSession对象
  • openSession(boolean)
    • openSession(true) 获取自动提交事务的SqlSession对象
    • openSession(false) 非自动提交事务的SqlSession对象

SqlSession

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

注意:

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

工具类代码

package org.hanxu.util;

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对象
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            factory = builder.build(in);

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

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

        }
        return sqlSession;

    }
}

工具类验证

有没有顿感 减少了很多代码量

package org.hanxu;

import org.apache.ibatis.session.SqlSession;
import org.hanxu.domain.Student;
import org.hanxu.util.MyBatisUtils;
import java.io.IOException;
import java.util.List;

public class MyApp_bak {
    public static void main(String[] args) throws IOException {

        //获取SqlSession对象,从SqlSessionFactory中获取SqlSession
        SqlSession sqlSession = MyBatisUtils.getSqlSession();

        //【重要】指定要执行的sql语句标识。sql映射文件的namespace+"."+标签的的id值
        String sqlId = "org.hanxu.dao.StudentDao" + "." + "selectStudents";

        //【重要】执行sql语句,通过sqlId找到语句
        List<Student> studentList = sqlSession.selectList(sqlId);

        //输出结果
        studentList.forEach(stu -> System.out.println(stu));

//        for(Student stu : studentList){
//            System.out.println("查询的学生="+stu);
//
//        }
        //9、关闭SqlSession对象
        sqlSession.close();
    }
}

IDEA创建常用文本模板

操作方法:

菜单栏File ——>Setting——>Eeditor——>File and Code Templates

在右边Files下面点击加号

Name:mybatis-mapper

Extension:xml

下面方块中复制:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="">  
    <select id="" resultType="">
    
    </select>
</mapper>

点击应用和ok


同理添加主配置文件模板

Name:mybatis-config

Extension:xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
    <environments default="mydev">
        <environment id="mydev">
    
            <transactionManager type="JDBC"/>
        
            <dataSource type="POOLED">
      
                <property name="driver" value="com.mysql.jdbc.Driver"/>

                <property name="url" value="jdbc:mysql://localhost:3306/test?useSSL=false"/>
     
                <property name="username" value="root"/>

                <property name="password" value="hanxu"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="org/hanxu/dao/StudentDao.xml"/>
    </mappers>
</configuration>

编写Dao功能实现类

package org.hanxu.impl;

import org.apache.ibatis.session.SqlSession;
import org.hanxu.dao.StudentDao;
import org.hanxu.domain.Student;
import org.hanxu.util.MyBatisUtil;

import java.util.List;

public class StudentDaoImpl implements StudentDao {
    @Override
    public List<Student> selectStudents() {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();

        String sql = "org.hanxu.dao.StudentDao.selectStudents";
        List<Student> list = sqlSession.selectList(sql);

        sqlSession.close();
        return list;
    }
}

测试程序

import org.hanxu.domain.Student;
import org.hanxu.impl.StudentDaoImpl;

import java.util.List;

public class APP {
    public static void main(String[] args) {
        StudentDaoImpl v = new StudentDaoImpl();

        List<Student> list = v.selectStudents();
        for (Student s: list) {
            System.out.println(s);
        }
    }
}

四、mybatis动态代理

mybatis的动态代理:mybatis根据dao接口的方法调用,获取执行sql语句的信息。mybatis根据你的dao接口的实现类,并创建这个类的对象。完成sqlsession调用方法,访问数据库。

我们删除掉之前自己创建的实现类,使用JDK的动态代理获取dao接口的实现类,来调用方法。

使用动态代理查询操作

    @Test
    public void  selectTest(){
        /**
         *使用动态代理机制,使用SqlSession.getMapper(dao接口)
         * getMapper可以获取dao接口的实现类对象
         */
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        List<Student> list = dao.selectStudents();
        for (Student stu:list
             ) {
            System.out.println(stu);
        }

    }

使用动态代理插入操作

 public void  insertTest(){

        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        Student student = new Student();
        student.setId(1102);
        student.setAge(30);
        student.setName("铁锤");
        student.setEmail("asahi@qq.com");

       int num =  dao.insertStudents(student);
       sqlSession.commit();
        System.out.println("添加成功"+num);
    }

在控制台打印输出动态代理

//com.sun.proxy.$Proxy2 JDK的动态代理
System.out.println(dao.getClass().getName());

五、深入理解参数

parameterType

接口中方法参数的类型,类型的完全限定名别名。这个属性是可选的,因为MyBatis可以推断出具体传入语句的参数,默认值为未设置(unset)。接口中方法的参数从java代码传入到mapper文件的sql语句。

mybatis参数别名
Alias Mapped Type
_byte byte
_long long
_short short
_int int
_integer int
_double double
_float float
_boolean boolean
string String
byte Byte
long Long
short Short
int Integer
integer Integer
double Double
float Float
boolean Boolean
date Date
decimal BigDecimal
bigdecimal BigDecimal
object Object
map Map
hashmap HashMap
list List
arraylist ArrayList
collection Collection
iterator Iterator

parameterType

写在mapper文件中的 一个属性。 表示dao接口中方法的参数的数据类型。

例如StudentDao接口

public Student  selectStudentById(Integer id) 

mapper文件

<select id="selectIdenById" parameterType="int" resultType="org.hanxu.domain.Student">
            select id,name,email,age from student where id = #{id}
</select>
<select id="selectIdenById" parameterType="java.lang.Integer" resultType="org.hanxu.domain.Student">
            select id,name,email,age from student where id = #{id}
</select>

MyBatis传递参数

从java代码中把参数传递到mapper.xml文件。

一个简单参数

mybatis把java的基本数据类型和String都叫简单类型。在mapper文件获取简单类型的一个参数的值,使用 #{任意字符}

//接口
public Student  selectStudentById(Integer id) 
<!--mapper-->
select id,name, email,age from student where id=#{studentId}

测试方法:

  @Test
    public void  selectTest(){
        /**
         *使用动态代理机制,使用SqlSession.getMapper(dao接口)
         * getMapper可以获取dao接口的实现类对象
         */
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
       Student stu = dao.selectIdenById(1102);
        System.out.println(stu);

    }

多个参数

(必会)使用@Param传参

接口

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

mapper文件

<!--多个参数命名-->
<select id="selectMulitParam" resultType="org.hanxu.domain.Student">
   select * from student where name=#{myname} or age=#{myage}
</select>

测试程序

    @Test
    public void selectMulitParamTest(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        List<Student> studentList = dao.selectMulitParam("铁锤", 30);
        for (Student stu:
                studentList
             ) {
            System.out.println(stu);
        }
        sqlSession.close();
    }

(必会)使用对象传参

Supported JDBC Types

BIT FLOAT CHAR TIMESTAMP OTHER UNDEFINED
TINYINT REAL VARCHAR BINARY BLOB NVARCHAR
SMALLINT DOUBLE LONGVARCHAR VARBINARY CLOB NCHAR
INTEGER NUMERIC DATE LONGVARBINARY BOOLEAN NCLOB
BIGINT DECIMAL TIME NULL CURSOR ARRAY

接口

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

mapper文件

    <!--
        多个参数命名,使用java对象的属性值,作为参数实际值
        使用对象语法:#{属性名,javaType=类型名称,jdbcType=数据类型}
        javaType:只java中的属性数据类型
        jdbcType:在数据库中的数据类型
        例如:#{paramName,javaType=java.lang.String,jdbcType=VARCHAR}

        简化方式:
        #{属性名} ,javaType,jdbcType的值mybatis反射机制能获取。不用提供
    -->
<!--    <select id="selectMulitObjectParam" resultType="org.hanxu.domain.Student">-->
<!--            select * from student where-->
<!--            name=#{paramName,javaType=java.lang.String,jdbcType=VARCHAR}-->
<!--            or age=#{paramAge,javaType=java.lang.integer,jdbcType=INTEGER}-->
<!--    </select>-->
    <select id="selectMulitObjectParam" resultType="org.hanxu.domain.Student">
            select * from student where
            name=#{paramName} or age=#{paramAge}
    </select>

参数类

package org.hanxu.vo;

public class QueryParam {
    private String paramName;
    private int paramAge;

    public String getParamName() {
        return paramName;
    }

    public void setParamName(String paramName) {
        this.paramName = paramName;
    }

    public int getParamAge() {
        return paramAge;
    }

    public void setParamAge(int paramAge) {
        this.paramAge = paramAge;
    }
}

测试程序

    @Test
    public void selectMulitObjectParamTest(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        QueryParam param = new QueryParam();
        param.setParamAge(30);
        param.setParamName("铁锤");
        List<Student> students = dao.selectMulitObjectParam(param);
        for (Student stu:
                students
        ) {
            System.out.println(stu);
        }

        sqlSession.close();
    }

(了解)按位置传参

参数位置从0开始,引用参数语法#{arg位置},第一个参数是#{arg0}, 第二个是#{arg1}注意:mybatis-3.3版本和之前的版本使用#{0},#{1}方式,从mybatis3.4开始使用#{arg0}方式。

接口方法

List<Student> selectByNameAndAge(String name,int age);

mapper文件

<select id="selectByNameAndAge" resultType="com.bjpowernode.domain.Student">
    select id,name,email,age from student where name=#{arg0} or age =#{arg1}
</select>

测试方法

@Testpublic void testSelectByNameAndAge(){
    //按位置参数
   SqlSession sqlSession = MyBatisUtil.getSqlSession();
   StudentDao dao = sqlSession.getMapper(StudentDao.class);
    List<Student> stuList = dao.selectByNameAndAge("李力",20);
    stuList.forEach( stu -> System.out.println(stu));
}

(了解)使用Map传参

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

接口方法

List<Student> selectMultiMap(Map<String,Object> map);

mapper文件

<select id="selectMultiMap" resultType="com.bjpowernode.domain.Student">
    select id,name,email,age from student where name=#{myname} or age =#{myage}
</select>

测试方法

@Testpublic void testSelectMultiMap(){
    SqlSession sqlSession = MyBatisUtil.getSqlSession();
    StudentDao dao = sqlSession.getMapper(StudentDao.class);
    Map<String,Object> data = new HashMap<>();
    data.put("myname","李力");// #{myname}
    data.put("myage",20);    // #{myage}
    List<Student> stuList = dao.selectMultiMap(data);
    stuList.forEach( stu -> System.out.println(stu));}

(必知)#和$

#:占位符

告诉mybatis使用实际的参数值代替。并使用PrepareStatement对象执行sql语句,#{...}代替sql语句的“?”。这样做更安全,更迅速,通常也是首选做法。

 <select id="selectIdenById" parameterType="int" resultType="org.hanxu.domain.Student">
            select id,name,email,age from student where id = #{id}
 </select>

mybatis执行的是

String sql=”select id,name,email,age from student where id=?”;
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1,1102);

解释

where id=? 就是where id=#{id}

ps.setInt(1,1102) , 1102会替换掉#{id}

$:字符串替换

告诉mybatis使用$包含的“字符串”替换所在位置。使用Statement把sql语句和${}的内容连接起来。主要用在替换表名,列名,不同列排序等操作。

例如:

<select id="selectIdenById" parameterType="int" resultType="org.hanxu.domain.Student">
    select id,name,email,age from student where id = ${id}
</select>

接口方法

Student findByDiffField(@Param("col") String colunName,@Param("cval") Object value);

mapper文件

<select id="findByDiffField"  resultType="com.bjpowernode.domain.Student">
    select * from student where ${col}=#{cval}
</select>

测试方法

@Test
public void testFindDiffField(){
    Student student1 = studentDao.findByDiffField("id",1002);
    System.out.println("按id列查询:"+student1);
    Student student2 = studentDao.findByDiffField("email","zhou@126.net");
    System.out.println("按email列查询:"+student2);
}

注意:$:可以替换表名或者列名, 你能确定数据是安全的。可以使用$

总结

  • mybatis的传递参数
    • 从java程序把数据传入到mapper文件的sql语句
    • dao方法有一个简单类型的参数,在mapper文件夹中,使用#
    • 使用@Param注解给参数命名,在mapper文件中,使用#
    • 使用java对象传参,在mapper文件中,使用#
    • 使用参数的位置,在mapper文件中,#
    • 使用map,#
  • \#和 $区别)
    • \#是占位符,使用?做占位符,mybatis内部使用PreparedStatement执行sql,效率高
    • \#表示列的值,一般是放在等号的右侧使用
    • \#能够避免sql注入,更安全。
    • $是字符串代理连接,把sql语句和${}位置的值连接在一起
    • $表示的内容时原样替换的
    • $有sql注入的风险,缺乏安全性。
    • $不使用占位符,是字符串连接方式,mybatis使用Statement对象执行sql的,效率低
    • $一般是替换列名、表名、部分sql语句的

六、封装MyBatis输出结果

resultType

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

结果类型,指sql语句执行完毕之后,数据转为的java对象。

  • mybatis执行sql语句,然后mybatis调用的无参构造方法,创建对象。
    • 返回对象不一定是实体类,也可以是自己自定义的类
  • mybatis把ResultSet指定列值赋给同名的属性。
  <select id="selectIdenById" parameterType="int" resultType="org.hanxu.domain.Student">
            select id,name,email,age from student 
  </select>

对等的JDBC

ResultSet rs= sta.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"))

			}

对象类型

接口方法

ViewStudent selectViewStudent(@Param("sid") Integer id);

mapper文件

<select id="selectViewStudent" resultType="org.hanxu.domain.ViewStudent">
            select * from student where id = #{sid}
</select>

自定义视图类

package org.hanxu.domain;

public class ViewStudent {
    private Integer id;
    private String name;

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

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

测试程序

    @Test
    public void selectViewStudentTest(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        ViewStudent stu = dao.selectViewStudent(1106);

        System.out.println(stu);

        sqlSession.close();
    }

简单类型

接口方法

int selectCount();

mapper文件

 <select id="selectCount" resultType="int">
        select count(*) from student
 </select>

测试程序

 @Test
    public void selectCountTest(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        int num = dao.selectCount();

        System.out.println(num);

        sqlSession.close();
    }

Map类型

接口方法

Map<Object,Object> selectMap(Integer id);

mapper文件

 <!--返回Map
        1、列名是map的key,列值是map的value
        2、只能最多返回一行记录,多余一行是不行的
 -->
    <select id="selectMap" resultType="map">
        select * from student where id = #{stuid}
    </select>

测试程序

    @Test
    public void selectMapTest(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        Map<Object, Object> map = dao.selectMap(1001);
        System.out.println(map);
    }
/*执行结果
<==    Columns: id, name, email, age
<==    Row: 1001, 李四, lisi@qq.com, 20
*/

自定义类型的别名

建议使用全限定名称。更加安全!
  • 在mybatis主配置文件中定义,使定义别名
    <typeAliases>
        <!--第一种方式-->
        <!--
        一行可以指定一个类型一个自定义别名
        type:自定义类型的全限定名称
        alias:别名(短小,容易记忆的)
        -->
        <typeAlias type="org.hanxu.domain.ViewStudent" alias="view"/>
     	<typeAlias type="org.hanxu.domain.Student" alias="stu"/>
        <!--第二种方式-->
        <!--
		<package> name是包名,包下面的所有类,类名就是别名(类名不区分大小写)
		-->
        <package name="org.hanxu.domain"/>
    </typeAliases>
  • 可以在mapper文件中的resultType中使用自定义别名
<!--第一种方式-->
<select id="selectViewStudent" resultType="view">
            select * from student where id = #{sid}
</select>

<!--第二种方式-->
<select id="selectViewStudent" resultType="ViewStudent">
            select * from student where id = #{sid}
</select>

测试程序

   @Test
    public void selectViewStudentTest(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        ViewStudent stu = dao.selectViewStudent(1106);

        System.out.println(stu);

        sqlSession.close();
    }

实体类属性名和数据库列名不同的处理方式

resultMap

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

使用方式:

  • 先定义resultMap,指定列名和属性的对应关系。
  • 在<select>中把resultType替换为resultMap。

接口方法

List<Student> selectResultMap();

mapper文件

   <!--
		创建resultMap:
		id:自定义的唯一名称,在<select>使用
		type:期望转为的java对象的全限定名称或别名
		-->
	<resultMap id="studentmap" type="org.hanxu.domain.Student">
        <!--主键字段使用id -->
        <id column="id" property="id" />
        <!--非主键字段使用result-->
        <result column="name" property="name"/>
        <result column="email" property="email" />
        <result column="age" property="age" />
    </resultMap>
	<!--resultMap: resultMap标签中的id属性值-->
    <select id="selectResultMap" resultMap="studentmap">
        select id,name,email,age from student
    </select>

测试程序

    @Test
    public void selectResultMapTest(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        List<Student> students = dao.selectResultMap();
        for (Student stu:students
             ) {
            System.out.println(stu);
        }
        sqlSession.close();
    }

使用列别名和<resultType>

resultType的默认原则是同名的列值赋值给同名的属性,使用列别名(java对象的属性名)

mapper文件

<select id="selectUseFieldAlias" resultType="com.bjpowernode.domain.PrimaryStudent">
    select id as stuId, name as stuName,age as stuAge from student where  name=#{queryName} or age=#{queryAge}
</select>

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

模糊查询like

模糊查询的实现有两种方式,一是java代码中给查询数据加上“%”; 二是在mapper文件sql语句的条件位置加上“%”

接口方法

List<Student> selectLike(String name);

mapper文件

<select id="selectLike" resultType="org.hanxu.domain.Student">

        select id, name,age from student where  name like #{name}
    </select>

测试程序

  @Test
    public void selectLikeTest(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        String name = "%铁%";
        List<Student> students = dao.selectLike(name);
        for (Student stu:students
        ) {
            System.out.println(stu);

        }
        sqlSession.close();
    }

还有一种方式就是在mapper文件中使用like name "%" #{xxx} "%"

七、MyBatis框架动态SQL

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

动态sql的实现,使用的是mybatis提供的标签,<if>、<where>、<foreach>

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

动态SQL-if

对于该标签的执行,当test的值为true时,会将其包含的SQL片断拼接到其所在的SQL语句中。

语法:<if test="条件"> sql语句的部分</if>

接口方法

List<Student> selectStudentIf(Student student);

mapper文件

    <select id="selectStudentIf" resultType="org.hanxu.domain.Student">
        select id,name,email,age from student where 1=1
        <if test="name !=null and name != ''">
            and name =#{name}
        </if>
        <if test="age > 0">
            and age > #{age}
        </if>
    </select>

测试方法

 @Test
    public void  selectTest(){

        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        Student student = new Student();
        student.setName("铁锤");
        student.setAge(40);
        List<Student> students = dao.selectStudentIf(student);
        for (Student stu:
                students
             ) {
            System.out.println(stu);

        }
        sqlSession.close();

    }

动态SQL-where

​ <if/>标签的中存在一个比较麻烦的地方:需要在where后手工添加1=1的子句。因为,若where后的所有<if/>条件均为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>

接口

List<Student> selectStudentWhere(Student student);

mapper文件

 <select id="selectStudentWhere" resultType="org.hanxu.domain.Student">
        select id,name,email,age from student
        <where>
            <if test="name !=null and name != ''">
                and name =#{name}
            </if>
            <if test="age > 0">
                or age > #{age}
            </if>
        </where>
    </select>

测试代码

@Test
    public void  selectStudentWhereTest(){

        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        Student student = new Student();
//        student.setName("铁锤");
//        student.setAge(2);
        List<Student> students = dao.selectStudentWhere(student);
        for (Student stu:
                students
        ) {
            System.out.println(stu);

        }
        sqlSession.close();

    }

动态SQL-foreach

<foreach/>标签用于实现对于数组与集合的遍历。对其使用,需要注意

  • collection表示要遍历的集合类型,list ,array等。
  • open、close、separator为对遍历内容的SQL拼接

语法:

<foreach collection="集合类型" open="开始的字符" close="结束的字符" item="集合中的成员" separator="集合成员之间的分隔符">
    #{item的值}
</foreach>

写一个自动拼接sql

    @Test
    public void  selectStudentForeachTest(){

        //SqlSession sqlSession = MyBatisUtil.getSqlSession();
        //StudentDao dao = sqlSession.getMapper(StudentDao.class);
        List<Integer> list = new ArrayList<>();
        list.add(1001);
        list.add(1002);
        list.add(1003);
        String sql = "select id,name,email,age from student where id in";
        StringBuffer stringBuffer = new StringBuffer();
        int init= 0;
        int len =list.size();
        stringBuffer.append("(");
        for (Integer i :
                list) {
            stringBuffer.append(i).append(",");
        }
        stringBuffer.deleteCharAt(stringBuffer.length()-1);
        stringBuffer.append(")");

        System.out.println(sql+stringBuffer.toString());
        sqlSession.close();

    }

//结果:select id,name,email,age from student where id in(1001,1002,1003)

遍历简单类型list

接口

List<Student> selectStudentForeach(List<Integer> list);

mapper文件

 <select id="selectStudentForeach" resultType="org.hanxu.domain.Student">
        select id,name,email,age from student where id in
        <foreach collection="list" item="myid" open="(" close=")" separator=",">
            #{myid}
        </foreach>
</select>

测试代码

  @Test
    public void  selectForeachTest(){

        SqlSession sqlSession = MyBatisUtil.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.selectStudentForeach(list);
        System.out.println(students);
        sqlSession.close();

    }

遍历对象类型list

接口方法

List<Student> selectStudentForList2(List<Student> stuList);

mapper文件

<select id="selectStudentForList2" resultType="com.bjpowernode.domain.Student">
    select id,name,email,age from student
    <if test="list !=null and list.size > 0 ">
        where id in
        <foreach collection="list" open="(" close=")" item="stuobject" separator=",">
            #{stuobject.id}
        </foreach>
    </if>
</select>

测试方法

@Test
public void testSelectForList2(){
    SqlSession sqlSession = MyBatisUtil.getSqlSession();
    StudentDao dao = sqlSession.getMapper(StudentDao.class);
    List<Student> list = new ArrayList<>();
    Student s1 = new Student();s1.setId(1002);
    list.add(s1);
    s1 = new Student();
    s1.setId(1005);
    list.add(s1);
    List<Student> studentList = dao.selectStudentForList2(list);
    studentList.forEach( stu -> System.out.println(stu));
}

动态SQL-片段复用

mapper文件

<!--创建sql片段id:片段的自定义名称-->
<sql id="sql">
    select id,name,email,age from student
</sql>

<select id="selectStudentWhere" resultType="org.hanxu.domain.Student">
     <!--引用sql片段-->   
    <include refid="sql"/>   
    <where>
       <if test="name !=null and name != ''">
                and name =#{name}
        </if>
        <if test="age > 0">
                or age >= #{age}
         </if>
     </where>
</select>

八、MyBatis配置文件

settings配置

<!-- settings是 MyBatis 中全局的调整设置,它们会改变 MyBatis 的运行时行为,应谨慎设置 -->  
<settings>  
    
	<!-- 该配置影响的所有映射器中配置的缓存的全局开关。默认值true -->  
	<setting name="cacheEnabled" value="true"/>  
    
	<!--延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态。默认值false  -->  
	<setting name="lazyLoadingEnabled" value="true"/> 
    
	<!-- 是否允许单一语句返回多结果集(需要兼容驱动)。 默认值true -->  
	<setting name="multipleResultSetsEnabled" value="true"/>  
	
    <!-- 
		使用列标签代替列名。不同的驱动在这方面会有不同的表现, 具体可参考相关驱动文档
		或通过测试这两种不同的模式来观察所用驱动的结果。默认值true 
	-->  
	<setting name="useColumnLabel" value="true"/>  
	
    <!-- 
		允许JDBC 支持自动生成主键,需要驱动兼容。 如果设置为 true 则这个设置强制使用
		自动生成主键,尽管一些驱动不能兼容但仍可正常工作(比如 Derby)。 默认值false
  	-->  
	<setting name="useGeneratedKeys" value="false"/>  
	
    <!--
		指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示取消自动映射;PARTIAL 
		只会自动映射没有定义嵌套结果集映射的结果集。 FULL 会自动映射任意复杂的结果集
		(无论是否嵌套)。 
	-->   
	<!-- 默认值PARTIAL -->  
	<setting name="autoMappingBehavior" value="PARTIAL"/>         
	<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>  
    
	<!--  配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句
		(prepared statements); BATCH 执行器将重用语句并执行批量更新。默认SIMPLE
  	-->  
    <setting name="defaultExecutorType" value="SIMPLE"/>  
	
    <!-- 设置超时时间,它决定驱动等待数据库响应的秒数。 -->  
	<setting name="defaultStatementTimeout" value="25"/>  
	<setting name="defaultFetchSize" value="100"/>  
	
    <!-- 允许在嵌套语句中使用分页(RowBounds)默认值False -->  
	<setting name="safeRowBoundsEnabled" value="false"/>  
    
	<!-- 
		是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典
 		Java 属性名 aColumn 的类似映射。  默认false
 	-->  
    
	<setting name="mapUnderscoreToCamelCase" value="false"/>  
	<!-- 
		MyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)
		和加速重复嵌套查询。  
		默认值为 SESSION,这种情况下会缓存一个会话中执行的所有查询。  
		若设置值为 STATEMENT,本地会话仅用在语句执行上,对相同 SqlSession 的不同调用将不会
		共享数据。  
	-->  
	<setting name="localCacheScope" value="SESSION"/> 
    
	<!--
		当没有为参数提供特定的 JDBC 类型时,为空值指定 JDBC 类型。 某些驱动需要指定列的
 		JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。  
	-->  
	<setting name="jdbcTypeForNull" value="OTHER"/>
    
	<!--指定哪个对象的方法触发一次延迟加载。-->  
	<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>  
    
</settings>  

mybatis主配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!--
    约束文件的说明
    mybatis-3-config.dtd:约束文件的名称
-->
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--
    mybatis的主配置文件:主要定义了数据库的配置信息。sql映射的位置。

    configuration 根标签
-->
<configuration>
    <!--
        环境配置:数据库的连接信息
        default 必须和某个environment的id一样
        告诉mybatis使用哪个数据库的链接信息,也就是访问哪个数据库
    -->
    <environments default="mydev">
        <!---->
        <!--environment 一个数据库信息的配置,环境
            id:一个唯一值,自定义,表示环境名称。
        -->
        <environment id="mydev">
            <!--
            transactionManager :mybatis的事务类型
            type:
				1、JDBC(表示使用jdbc中的connection对象commit,rollback做事务处理)
				2、MANAGED:把mybatis的事务处理委托给其他容器(一个服务器软件、一个框架(spring))
            -->
            <transactionManager type="JDBC"/>
            <!--
                dataSource:表示数据源 连接数据库的
                type:表示数据源的类型,POOLED表示使用连接池
				在java体系中,规定实现了javax.sql.DataSource接口的都是数据源
				数据源就是表示链接Connection对象的。
				type:指定的数据源类型
				1)POOLED:使用链接池,mybatis会创建PooledDataSource类对象
				2)UnpooledDataSource:不使用连接池,在每一次执行sql语句,先创建链接,执行sql,再关闭						链接。mybatis会创建一个UnpooledDataSource,管理connection对象的使用
				3)JNDI:java命名和目录服务(Windows注册表)
            -->
            <dataSource type="POOLED">
                <!--driver,url,username,password是固定的,不能自定义-->
                <!--数据库的驱动-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <!--连接数据库的url字符串-->
                <property name="url" value="jdbc:mysql://localhost:3306/test?useSSL=false"/>
                <!--访问数据库的用户名-->
                <property name="username" value="root"/>
                <!--访问数据库的密码-->
                <property name="password" value="hanxu"/>
            </dataSource>
        </environment>
    </environments>
    <!--sql mapper(sql映射文件)的位置-->
    <mappers>
        <!--一个mapper标签指定一个文件的位置
            从类路径开始的路径信息 target\classes(类路径)
        -->
<!--        <mapper resource="org/mybatis/example/BlogMapper.xml"/>-->
        <mapper resource="org/hanxu/dao/StudentDao.xml"/>
    </mappers>
</configuration>

数据库的属性配置文件

把数据库连接信息放到一个单独的文件中。 和mybatis主配置文件分开。目的是便于修改,保存,处理多个数据库的信息。

  • 在resources目录中定义一个属性配置文件, xxxx.properties ,例如 jdbc.properties
    • 在属性配置文件中, 定义数据,格式是 key=value
    • key: 一般使用 . 做多级目录的。
例如 
jdbc.mysql.driver或jdbc.driver, mydriver
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql//.....
jdbc.username=root
jdbc.password=123456
  • 在mybatis的主配置文件,使用<property> 指定文件的位置
    • 在需要使用值的地方, $

在resources目录下定义jdbc.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test?useSSL=false
jdbc.username=root
jdbc.password=hanxu

mybatis的主配置文件,使用<property> 指定文件的位置

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
    <!--
        指定properties文件位置,从类路径根开始找文件的
    -->
    <properties resource="jdbc.properties"/>
    <settings>
        <!--设置mybatis输出日志-->
        <setting name="logImpl" value="STDOUT_LOGGING" />
    </settings>

    <!--定义别名-->
    <typeAliases>
        <!--
        可以指定一个类型一个自定义别名
        type:自定义类型的全限定名称
        alias:别名(短小,容易记忆的)
        -->
        <typeAlias type="org.hanxu.domain.ViewStudent" alias="view"/>
        
        <package name="org.hanxu.domain"/>
    </typeAliases>
    <environments default="mydev">
        <environment id="mydev">

            <transactionManager type="JDBC"/>

            <dataSource type="POOLED">

                <property name="driver" value="${jdbc.driver}"/>

                <property name="url" value="${jdbc.url}"/>

                <property name="username" value="${jdbc.username}"/>

                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="org/hanxu/dao/StudentDao.xml"/>
    </mappers>
</configuration>

mapper文件映射

第一种方式: 指定多个mapper文件

<mappers>
        <mapper resource="org/hanxu/dao/StudentDao.xml"/>
   		 <mapper resource="org/hanxu/dao/OrderDao.xml"/>
</mappers>

第二种方式: 使用包名

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

九、扩展PageHelper

https://github.com/pagehelper/Mybatis-PageHelper

PageHelper支持多种数据库:
1.Oracle
2.Mysql
3.MariaDB
4.SQLite
5.Hsqldb
6.PostgreSQL
7.DB2
8.SqlServer(2005,2008)
9.Informix
10.H2
11.SqlServer2012
12.Derby
13.Phoenix

maven坐标

 <dependency>
      <groupId>com.github.pagehelper</groupId>
      <artifactId>pagehelper</artifactId>
      <version>5.1.10</version>
</dependency>

加入plugin配置

在主配置文件中<environments>之前加入

<plugins>
   <plugin interceptor="com.github.pagehelper.PageInterceptor"/>
</plugins>

测试代码

@Test
    public void  selectAllTest(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        PageHelper.startPage(2,3);
        /**加入PageHelper的方法,分页
         *  pageNum:第几页数据,从1开始
         *  pageSize:一页中有多少数据
         */
        List<Student> students = dao.selectAll();
        for (Student stu :
                students) {
            System.out.println(stu);
        }
        sqlSession.close();
    }

踩坑idea2020.1版本

maven仓库中使用默认仓库,idea手动指定仓库位置。否则找不到包!

posted @ 2021-03-10 14:57  Asahi_煦  阅读(355)  评论(2)    收藏  举报