Mybatis-1

1.关于Mybatis

1.1.简介

​ mybatis就是一个封装来jdbc的持久层框架,它和hibernate都属于ORM(对象关系映射)框架,但是具体的说,hibernate是一个完全的orm框架,而mybatis是一个不完全的orm框架。

​ MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。

​ Mybatis让程序员只关注sql本身,而不需要去关注如连接的创建、statement的创建等操作

​ Mybatis会将输入参数、输出结果进行映射 输入参数是对象 输出结果也是对象

1.2.历史

​ 原是Apache的一个开源项目iBatis, 2010年6月这个项目由Apache Software Foundation 迁移到了

Google Code,随着开发团队转投Google Code旗下, iBatis3.x正式更名为MyBatis

mybatis项目地址

官方文档地址

1.3.优势

为什么使用mybatis

  • MyBatis是一个半自动化的持久化层框架
  • 对开发人员而言,核心sql还是需要自己优化
  • sql和java编码分开,功能边界清晰,一个专注业务、一个专注数据

对比

  • JDBC
    • SQL夹在Java代码块里,耦合度高导致硬编码内伤
    • 维护不易且实际开发需求中sql是有变化,频繁修改的情况多见
  • Hibernate和JPA:(目标旨在消除sql)
    • 长难复杂SQL,对于Hibernate而言处理也不容易
    • 内部自动生产的SQL,不容易做特殊优化。
    • 基于全映射的全自动框架,大量字段的POJO进行部分映射时比较困难。导致数据库性能下降.

1.4.JDBC问题简单解析

1.4.1.代码

public static void main(String[] args) {
	Connection connection = null;
	PreparedStatement preparedStatement = null;
	ResultSet resultSet = null;

	try {
		// 加载数据库驱动
		Class.forName("com.mysql.jdbc.Driver");

		// 通过驱动管理类获取数据库链接
		connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8", "root", "root");
		// 定义sql语句 ?表示占位符
		String sql = "select * from user where username = ?";
		// 获取预处理statement
		preparedStatement = connection.prepareStatement(sql);
		// 设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值
		preparedStatement.setString(1, "王五");
		// 向数据库发出sql执行查询,查询出结果集
		resultSet = preparedStatement.executeQuery();
		// 遍历查询结果集
		while (resultSet.next()) {
			System.out.println(resultSet.getString("id") + "  " + resultSet.getString("username"));
		}
	} catch (Exception e) {
		e.printStackTrace();
	} finally {
		// 释放资源
		if (resultSet != null) {
			try {
				resultSet.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if (preparedStatement != null) {
			try {
				preparedStatement.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if (connection != null) {
			try {
				connection.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

1.4.2.问题分析

  • 数据库连接创建、释放频繁造成系统资源浪费,从而影响系统性能。如果使用数据库连接池可解决此问题
  • Sql语句在代码中硬编码,造成代码不易维护,实际应用中sql变化的可能较大,sql变动需要改变java代码
  • 使用preparedStatement向占有位符号传参数存在硬编码,因为sql语句的where条件不一定,可能多也可能少,修改sql还要修改代码,系统不易维护
  • 对结果集解析存在硬编码(查询列名),sql变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成pojo对象解析比较方便

1.5.Mybatis工作原理图

在这里插入图片描述

步骤流程解释

  1. mybatis配置SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息,mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载
  2. 通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂
  3. 由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行
  4. mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器
  5. Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id
  6. Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数
  7. Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程

2.快速入门

2.1.环境相关

开发环境:

  • Jdk:1.8
  • Mybatis:3.4.5
  • 数据库:MySQL

需求:

完成初步的增删查改操作

相关的依赖jar包

  • Mybatis的核心包和依赖包

  • MySQL的驱动包

  • Junit 单元测试包

  • Log4j的日志包

<dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.6</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.20</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.16</version>
        </dependency>
</dependencies>

2.2.入门程序

2.2.1.相关代码

创建相关数据库

自主创建相关测试数据库

实体类

/**
 * 学生的实体类
 * @author DDDeng
 *
 */
public class Student {
   private String sno;
   private String sname;
   private String sex;
   private String sage;
   private String shobbies;
   private String sphoto;
  
  // 自主生成getter/setter和构造函数
}

2.2.2.配置文件

全局配置文件

​ 配置文件可以创建在resource文件夹

​ 全局配置文件中配置了事务管理器和数据库连接池的配置。事务使用jdbc事务,连接池使用mybatis提供的默认连接池

<?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">
            <!-- 使用jdbc管理事务mybatis -->
            <transactionManager type="JDBC"/>
            <!-- 数据库连接池 mybatis内置的一个数据库连接池-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
              <property name="url" value="jdbc:mysql://localhost:3306/stumanager"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
</configuration>

sql映射文件

同样的将SQL的映射文件创建在resource的目录下

<?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">
<!-- namespace属性就是当前mapper映射文件的id-->
<mapper namespace="Student">
    <select id="findAllStudent" resultType="com.test.model.Student">
        SELECT * FROM t_student
    </select>
</mapper>

注意:需要在全局配置文件中添加sql映射文件

<!-- 加载映射文件 -->
<mappers>
    <!-- resource就是写映射文件所在的地方 -->
    <mapper resource="StudentMapper.xml"/>
</mappers>

2.2.3.单元测试类

利用junit写一个单元测试类来测试程序是否能够正常运行.

@Test
public void findAllstudent() throws IOException {
    //将全局配置读入
    InputStream in= Resources.getResourceAsStream("mybatis-config.xml");
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
    //获取到一个sql会话
    SqlSession sqlSession=sqlSessionFactory.openSession();
    //查询List的写法 namespace.mapper的id
    List<Student> rs=sqlSession.selectList("Student.findAllStudent");
    for (Student stu :rs) {
        System.out.println(stu);
    }
    //关闭资源
    sqlSession.close();
}

2.2.4.关于日志

​ 在整个程序的执行过程中可以看见我们还没有办法完全看到整个程序的执行过程与状态,这个时候我们需要加入相关的日志jar包和配置,才可以完整的看见mybatis的运行过程和相关的输出信息

​ 在resources下创建log4j.properties的文件配置日志(Mybatis默认的日志输出是log4j)配置日志的输出是DEBUG级别 控制台输出

#全局配置
log4j.rootLogger=DEBUG,console
#debug 测试阶段使用
#控制台日志输出
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%p] %m %n

2.3.深化理解

2.3.1.查询强化

需求: 根据id查询(需要携带参数)

sql映射文件

<!-- 根据ID查询相关信息-->
<!--需求:通过id查询学生的记录-->
<!--
    1.id属性: 标识映射文件中的sql,将sql语句封装到mapped statement对象中,   所以称为statement的id
    2.parameterType:指定输入参数类型
    3.#{}:表示一个占位符
    4.#{id}:其中的id表示接收的输入参数,如果输入参数是简单类型,
    5.#{}中的参数名可以任意,可以为value或者其他
    6.resultType:指定sql输出结果的所映射的java对象类型,select指定resultType表示将单条记录映射成的java对象
-->
<select id="findById" resultType="com.test.model.Student">
    select * from t_student where sno=#{id}
</select>

单元测试代码

@Test
public void findById(){
  	//将全局配置读入
    InputStream in= Resources.getResourceAsStream("mybatis-config.xml");
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
  
    SqlSession sqlSession=sqlSessionFactory.openSession();
    Student stu=sqlSession.selectOne("Student.findById",324);
    System.out.println(stu);
    //关闭资源
    sqlSession.close();
}

优化测试类

将加载配置统一提取出来

public class StudentDaoTest {
    private SqlSessionFactory factory;

    @Before
    public void setUp() throws Exception {
        //将全局配置读入
        InputStream in= Resources.getResourceAsStream("mybatis-config.xml");
        factory=new SqlSessionFactoryBuilder().build(in);
        
    }
}

2.3.2.实现接口式编程

编写dao接口

public interface StudentDao {
    /**
     * 根据ID查询
     *
     * @param sno 主键
     * @return 
     */
    Student getById(Long sno);

    /**
     * 查询所有
     */
    List<Student> findAll();

    /**
     * 根据学生名称模糊查询
     *
     * @param sname
     * @return 
     */
    List<Student> findBySname(String sname);

    /**
     * 新增
     *
     * @param stu
     * @return
     */
    void insert(Student stu);

    /**
     * 更新
     *
     * @param stu
     * @return
     */
    void update(Student stu);

    /**
     * 删除
     *
     * @param sno
     * @return
     */
    void deleteById(Long sno);
}

dao接口的实现

需要注意的地方是涉及到增删改部分的时候会话需要提交才会生效

private SqlSessionFactory factory;

//创建构造函数将工厂传入(方便进行单元测试)
public StudentDaoImpl(SqlSessionFactory sqlSessionFactory) {
    this.factory = sqlSessionFactory;
}

@Override
public Student getById(Long sno) {
    //创建会话
    SqlSession sqlSession=factory.openSession();
    //执行查询
    Student stu=sqlSession.selectOne("Student.findById",sno.intValue());
    sqlSession.close();
    return stu;
}

@Override
public List<Student> findAll() {
    return null;
}

/**
 * 根据名字模糊查询
 * @param sname
 * @return
 */
@Override
public List<Student> findBySname(String sname) {
    //打开一个会话工厂
    SqlSession sqlSession=factory.openSession();
    //进行查询
    List<Student> list = sqlSession.selectList("Student.findBySname",sname);
    sqlSession.close();
    return list;

}

@Override
public void insert(Student stu) {
    SqlSession sqlSession=factory.openSession();
    sqlSession.insert("Student.insert",stu);
    //mybatis默认是不自动提交事务的所以要手动提交
    sqlSession.commit();
    sqlSession.close();
}

@Override
public void update(Student stu) {
    SqlSession sqlSession=factory.openSession();
    sqlSession.update("Student.update",stu);
    //mybatis默认是不自动提交事务的所以要手动提交
    sqlSession.commit();
    sqlSession.close();
}

@Override
public void deleteById(Long sno) {
    SqlSession sqlSession=factory.openSession();
    sqlSession.delete("Student.deleteById",sno.intValue());
    //mybatis默认是不自动提交事务的所以要手动提交
    sqlSession.commit();
    sqlSession.close();
}

sql映射文件

注意:涉及到模糊查询初步内容的时候,要搞清楚${}与#{}的区别

<!-- 查询所有 -->
   <select id="findAllStudent" resultType="com.test.model.Student">
       SELECT * FROM t_student
   </select>
   <!-- 根据ID查询相关信息-->
   <!--需求:通过id查询学生的记录-->
   <!--
       1.id属性: 标识映射文件中的sql,将sql语句封装到mapped statement对象中,   所以称为statement的id
       2.parameterType:指定输入参数类型
       3.#{}:表示一个占位符
       4.#{id}:其中的id表示接收的输入参数,如果输入参数是简单类型,
       5.#{}中的参数名可以任意,可以为value或者其他
       6.resultType:指定sql输出结果的所映射的java对象类型,select指定resultType表示将单条记录映射成的java对象
   -->
   <select id="findById" parameterType="java.lang.Integer" resultType="com.test.model.Student">
       select * from t_student where sno=#{id}
   </select>

   <!--
    1.需求根据产品分类名称模糊查询
    2.思路:模糊查询返回结果可能是多条纪录
    3.resultType:指定就是单条记录所映射成java对象类型
    4.${}:表示拼接sql串,将接收到参数的内容不加任何修饰拼接在sql中
    5.使用${}容易引起sql注入
    6.${value}:接受输入参数的内容,如果传入类型是简单类型,${}中只能用value
-->
   <select id="findBySname" parameterType="java.lang.String" resultType="com.test.model.Student">
      select * from t_student where sname like '%${value}%'
  </select>

   <!--插入-->
   <insert id="insert" parameterType="com.test.model.Student">
       insert into t_student (
       sname, sex, sage, shobbies, sphoto
       ) values (
         #{sname},
         #{sex},
         #{sage},
         #{shobbies},
         #{sphoto}
       )
   </insert>

   <update id="update" parameterType="com.test.model.Student">
       update t_student set
         sname=#{sname},
         sex= #{sex},
         sage=#{sage},
         shobbies=#{shobbies},
         sphoto=#{sphoto} where sno=#{sno}
   </update>

   <delete id="deleteById" parameterType="java.lang.Integer" >
       DELETE from t_student where sno=#{sno}
   </delete>

单元测试

public class StudentDaoTest {
    private SqlSessionFactory factory;
    private StudentDao dao;

    @Before
    public void setUp() throws Exception {
        //将全局配置读入
        InputStream in= Resources.getResourceAsStream("mybatis-config.xml");
        factory=new SqlSessionFactoryBuilder().build(in);
        //初始化构造dao
        dao=new StudentDaoImpl(factory);
    }

    @Test
    public void getById() {

    }

    @Test
    public void findAll() {

    }

    @Test
    public void findBySname() {
        System.out.println(dao.findBySname("Deng"));
        //第二种方式是用#{} 传值的时候拼接好如下
//        dao.findBySname("%Deng%");
    }

    @Test
    public void insert() {
        //自己创建学生信息传给dao层
        Student stu = new Student();
        stu.setSage("12");
        stu.setSname("xx");
        stu.setSex("男");
        dao.insert(stu);
    }

    @Test
    public void update() {
        Student stu=dao.getById((long) 325);
        stu.setSname("这是新的测试数据");
        dao.update(stu);
    }

    @Test
    public void deleteById() {
        dao.deleteById((long) 325);
    }
}

2.3.3.注意事项

  • #{}和${}

    #{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换。#{}可以有效防止sql注入。 #{}可以接收简单类型值或pojo属性值。 如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称

    $ {} 表示拼接sql串 ,通过${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换, $ {}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value

  • 为什么还需要${}?

    • 某些特定场景下只能用${},比如order by 后的排序字段,表名、列名,因为需要替换为不变的常量。如果表名中使用#{}的话,会变成如下
    select * from #{tablename}-->tablename传参为t_user --->处理后变成 
    select * from 't_user' -- 没有这样的表名,这样的话就会报错了,order by 同理。
    
  • parameterType和resultType

    parameterType:指定输入参数类型,mybatis通过输入对象中获取参数值拼接在sql中。

    resultType:指定输出结果类型,mybatis将sql查询结果的一行记录数据映射为resultType指定类型的对象。如果有多条数据,则分别进行映射,并把对象放到容器List中

  • selectOne和selectList

    selectOne查询一条记录,如果使用selectOne查询多条记录则抛出异常:

    org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 3 at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:70)

    selectList可以查询一条或多条记录

  • 关于原始Dao开发的问题

    • Dao方法体存在重复代码:通过SqlSessionFactory创建SqlSession,调用SqlSession的数据库操作方法
    • 调用sqlSession的数据库操作方法需要指定statement的id,这里存在硬编码,不得于开发维护

2.4.Mybatis面向接口动态代理

Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法

可以解决之前关于原始dao开发出现的问题

2.4.1.开发规范

  1. Mapper.xml文件中的namespace与mapper接口的类路径相同
  2. Mapper接口方法名和Mapper.xml中定义的每个statement的id相同
  3. Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同
  4. Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同

2.4.2.相关程序

可以在之前的入门程序上进行修改,修改的内容如下

  • 摒弃dao接口的实现类

  • dao接口类

    • Dao接口类中的方法名要和所对应的Mapper.xml中的id相同
  • sql映射文件

    • 映射文件的namespace的值要等于所对应的Mapper接口类的路径
    • 每个查询的paramType的类型要和接口的传参类型对应
    • 每个返回结果的resultType的类型要和接口的返回值类型对应
  • 单元测试

     /**
         * 通过测试类来测试Mapper的动态的代理
         * 核心配置仍然要导入
         */
        private SqlSessionFactory sqlSessionFactory;
    
        @Before
        public void setUp() throws Exception {
            // 加载mybatis的核心配置文件
            InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
            // SqlSessionFactory工厂创建
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
        }
    
    
        @Test
        public void test() {
            //会话仍然是要的
            SqlSession sqlSession=sqlSessionFactory.openSession();
            //通过会话获取动态mapper
            StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
            //增删查改
            //查
            Student ByidStu = mapper.findById(324);
            System.out.println(ByidStu);
            /** 增删改都还需要提交事物*/
            //改
            ByidStu.setSex("女");
            mapper.update(ByidStu);
            sqlSession.commit();
            //增
    //        ByidStu.setSno(null);
    //        mapper.insert(ByidStu);
    //        sqlSession.commit();
            //删
            //...
            //最后也是要关闭资源的
            sqlSession.close();
    
        }
    

2.4.3.注意事项

  • selectOne和selectList

    动态代理对象调用sqlSession.selectOne()和sqlSession.selectList()是根据mapper接口方法的返回值决定,如果返回list则调用selectList方法,如果返回单个对象则调用selectOne方法

  • namespace

    mybatis官方推荐使用mapper代理方法开发mapper接口,程序员不用编写mapper接口实现类,使用mapper代理方法时,输入参数可以使用pojo包装对象或map对象,保证dao的通用性

  • 关于SqlSession

    • SqlSession 的实例不是线程安全的,因此是不能被共享的
    • SqlSession每次使用完成后需要正确关闭,这个关闭操作是必须的
    • SqlSession可以直接调用方法的id进行数据库操 作,但是我们一般还是推荐使用SqlSession获取到Dao接口的代理类,执行代理对象的方法,可以更安全的进行类型检查操作

3.关于Mybatis配置文件

3.1.配置文件结构

MyBatis 的配置文件包含了影响 MyBatis 行为甚深的设置(settings)和属性(properties)信息。文档的顶层结构如下:


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

3.2.properties属性

  • driver=com.mysql.jdbc.Driver

  • url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8

  • username=root

  • password=123456

  • properties属性可以加载外部的properties的文件

3.3.settings属性

这是 MyBatis 中极为重要的调整设置,它们会改变MyBatis 的运行时行为

设置参数描述有效值默认值
cacheEnabled该配置影响的所有映射器中配置的缓存的全局开关true|falseTRUE
lazyLoadingEnabled延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态。true|falseFALSE
useColumnLabel使用列标签代替列名。 不同的驱动在这方面会有不同的表现,具体可参考相关驱动文档或通过测试这两种不同的模式来观察所用驱动的结果true|falseTRUE
defaultStatementTimeout设置超时时间,它决定驱动等待数据库相应的秒数Any positive integerNot Set(null)
mapUnderscoreToCamelCase是否开启自动驼峰命名规则映射,即从经典数据库列名A_COLUMN到经典Java属性名aColumn的类似映射true|falseFALSE

在这里插入图片描述

3.4.typeAliases别名处理器

类型别名是为 Java 类型设置一个短的名字,可以方便我们引用某个类

​ 在config文件中进行设置

<typeAliases>
        <typeAlias type="com.test.model.Student" alias="student"/>
</typeAliases>

之后在引用到相关的Student类的时候可以直接使用别名

<select id="findAllStudent" resultType="student">
        SELECT * FROM t_student
</select>

类很多的情况下,可以批量设置别名这个包下的每一个类创建一个默认的别名,就是简单类名小写

<typeAliases>
        <package name="com.test.model"/>
</typeAliases>

也可以使用@Alias注解为其指定一个别名

@Alias("author")
public class Author {
    ...
}

值得注意的是,MyBatis已经为许多常见的Java类型内建了相应的类型别名。它们都是大小写不敏感的,我们在起别名的时候千万不要占用已有的别名

别名映射的类型
_bytebyte
_longlong
_shortshort
_intint
_integerint
_doubledouble
_floatfloat
_booleanboolean
stringString
byteByte
longLong
shortShort
intInteger
integerInteger
doubleDouble
floatFloat
booleanBoolean
dateDate
decimalBigDecimal
bigdecimalBigDecimal
objectObject
mapMap
hashmapHashMap
listList
arraylistArrayList
collectionCollection
iteratorIterator

3.5.typeHandlers(类型处理器)

MyBatis 在设置预处理语句(PreparedStatement)中的参数或从结果集中取出一个值时, 都会用类型处理器将获取到的值以合适的方式转换成 Java 类型。下表描述了一些默认的类型处理器。

提示 从 3.4.5 开始,MyBatis 默认支持 JSR-310(日期和时间 API)

类型处理器Java 类型JDBC 类型
BooleanTypeHandlerjava.lang.Boolean, boolean数据库兼容的 BOOLEAN
ByteTypeHandlerjava.lang.Byte, byte数据库兼容的 NUMERICBYTE
ShortTypeHandlerjava.lang.Short, short数据库兼容的 NUMERICSMALLINT
IntegerTypeHandlerjava.lang.Integer, int数据库兼容的 NUMERICINTEGER
LongTypeHandlerjava.lang.Long, long数据库兼容的 NUMERICBIGINT
FloatTypeHandlerjava.lang.Float, float数据库兼容的 NUMERICFLOAT
DoubleTypeHandlerjava.lang.Double, double数据库兼容的 NUMERICDOUBLE
BigDecimalTypeHandlerjava.math.BigDecimal数据库兼容的 NUMERICDECIMAL
StringTypeHandlerjava.lang.StringCHAR, VARCHAR
ClobReaderTypeHandlerjava.io.Reader-
ClobTypeHandlerjava.lang.StringCLOB, LONGVARCHAR
NStringTypeHandlerjava.lang.StringNVARCHAR, NCHAR
NClobTypeHandlerjava.lang.StringNCLOB
BlobInputStreamTypeHandlerjava.io.InputStream-
ByteArrayTypeHandlerbyte[]数据库兼容的字节流类型
BlobTypeHandlerbyte[]BLOB, LONGVARBINARY
DateTypeHandlerjava.util.DateTIMESTAMP
DateOnlyTypeHandlerjava.util.DateDATE
TimeOnlyTypeHandlerjava.util.DateTIME
SqlTimestampTypeHandlerjava.sql.TimestampTIMESTAMP
SqlDateTypeHandlerjava.sql.DateDATE
SqlTimeTypeHandlerjava.sql.TimeTIME
ObjectTypeHandlerAnyOTHER 或未指定类型
EnumTypeHandlerEnumeration TypeVARCHAR 或任何兼容的字符串类型,用来存储枚举的名称(而不是索引序数值)
EnumOrdinalTypeHandlerEnumeration Type任何兼容的 NUMERICDOUBLE 类型,用来存储枚举的序数值(而不是名称)。
SqlxmlTypeHandlerjava.lang.StringSQLXML
InstantTypeHandlerjava.time.InstantTIMESTAMP
LocalDateTimeTypeHandlerjava.time.LocalDateTimeTIMESTAMP
LocalDateTypeHandlerjava.time.LocalDateDATE
LocalTimeTypeHandlerjava.time.LocalTimeTIME
OffsetDateTimeTypeHandlerjava.time.OffsetDateTimeTIMESTAMP
OffsetTimeTypeHandlerjava.time.OffsetTimeTIME
ZonedDateTimeTypeHandlerjava.time.ZonedDateTimeTIMESTAMP
YearTypeHandlerjava.time.YearINTEGER
MonthTypeHandlerjava.time.MonthINTEGER
YearMonthTypeHandlerjava.time.YearMonthVARCHARLONGVARCHAR
JapaneseDateTypeHandlerjava.time.chrono.JapaneseDateDATE

3.6.environments环境

MyBatis可以配置多种环境,比如开发、测试和生产环境需要有不同的配置

  • 每种环境使用一个environment标签进行配置并指 定唯一标识符
  • 可以通过environments标签中的default属性指定一个环境的标识符来快速的切换环境

关于transactionManager

  • type: JDBC | MANAGED | 自定义
    • JDBC:使用了 JDBC 的提交和回滚设置,依赖于从数据源得到的连接来管理事务范围。JdbcTransactionFactory
    • MANAGED:不提交或回滚一个连接、让容器来管理 事务的整个生命周期(比如 JEE 应用服务器的上下文)。 ManagedTransactionFactory
    • 自定义:实现TransactionFactory接口,type=全类名/ 别名

关于数据库连接池dataSource

  • type: UNPOOLED | POOLED | JNDI | 自定义

    – UNPOOLED:不使用连接池, UnpooledDataSourceFactory

    – POOLED:使用连接池, PooledDataSourceFactory

    – JNDI: 在EJB 或应用服务器这类容器中查找指定的数

    据源

    – 自定义:实现DataSourceFactory接口,定义数据源的获取方式。

  • 实际开发中我们使用Spring管理数据源,并进行事务控制的配置来覆盖上述配置

3.7.mapper映射

官方文档

mapper逐个注册SQL映射文件

		<mappers>
        <mapper resource="StudentMapper.xml"></mapper>
        <mapper url="file:///D:/StudentMapper.xml"></mapper>
        <mapper class="com.test.dao.StudentDao"></mapper>
    </mappers>

注意:如果用class接口限定sql映射文件需要满足以下条件

  1. 接口名与映射文件名相同

  2. maven因为扫描规则的原因不会扫面java包下的资源所以需要增加以下代码

    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                    <include>**/*.properties</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.xml</include>
                    <include>**/*.properties</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>
    
  3. 将映射文件与配置文件放在同一文件夹下

测试代码

@Test
public void findAllStudent() throws IOException {
  //将全局配置读入
  InputStream in= Resources.getResourceAsStream("mybatis-config.xml");
  SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
  //获取到一个sql会话
  SqlSession sqlSession=sqlSessionFactory.openSession();
  //查询List的写法 获取动态实现接口
  StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
  List<Student> rs = mapper.findAllStudent();
  for (Student stu :rs) {
    System.out.println(stu);
  }
  //关闭资源
  sqlSession.close();
}

批量注册

<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
  <package name="org.mybatis.builder"/>
</mappers>

3.8.关于数据库厂商标识

主要目的是为了能在多环境下适配多种数据库

官方参考

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值