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(框架)
 
框架
框架是一个舞台, 一个模版。 框架是一个软件,半成品的软件,定义好了一些基础功能, 需要加入你的功能就是完整的。
基础功能是可重复使用的,可升级的。
模版:
- 规定了好一些条款,内容。
 - 加入自己的东西
 
框架是一个模块
- 框架中定义好了一些功能。这些功能是可用的。
 - 可以加入项目中自己的功能, 这些功能可以利用框架中写好的功能。
 
框架特点
- 框架一般不是全能的, 不能做所有事情
 - 框架是针对某一个领域有效。 特长在某一个方面,比如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表。
 

- 加入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手动指定仓库位置。否则找不到包!

                
            
浙公网安备 33010602011771号