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
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工作原理图
步骤流程解释
- mybatis配置SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息,mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载
- 通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂
- 由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行
- mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器
- Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id
- Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数
- 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.开发规范
- Mapper.xml文件中的namespace与mapper接口的类路径相同
- Mapper接口方法名和Mapper.xml中定义的每个statement的id相同
- Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同
- 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(配置)
- properties(属性)
- settings(设置)
- typeAliases(类型别名)
- typeHandlers(类型处理器)
- objectFactory(对象工厂)
- plugins(插件)
- environments(环境配置)
- environment(环境变量)
- transactionManager(事务管理器)
- dataSource(数据源)
- environment(环境变量)
- databaseIdProvider(数据库厂商标识)
- mappers(映射器)
文件头(也可以在官方文档中查询)
<?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|false | TRUE |
lazyLoadingEnabled | 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态。 | true|false | FALSE |
useColumnLabel | 使用列标签代替列名。 不同的驱动在这方面会有不同的表现,具体可参考相关驱动文档或通过测试这两种不同的模式来观察所用驱动的结果 | true|false | TRUE |
defaultStatementTimeout | 设置超时时间,它决定驱动等待数据库相应的秒数 | Any positive integer | Not Set(null) |
mapUnderscoreToCamelCase | 是否开启自动驼峰命名规则映射,即从经典数据库列名A_COLUMN到经典Java属性名aColumn的类似映射 | true|false | FALSE |
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类型内建了相应的类型别名。它们都是大小写不敏感的,我们在起别名的时候千万不要占用已有的别名
别名 | 映射的类型 |
---|---|
_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 |
3.5.typeHandlers(类型处理器)
MyBatis 在设置预处理语句(PreparedStatement)中的参数或从结果集中取出一个值时, 都会用类型处理器将获取到的值以合适的方式转换成 Java 类型。下表描述了一些默认的类型处理器。
提示
从 3.4.5 开始,MyBatis 默认支持 JSR-310(日期和时间 API)
类型处理器 | Java 类型 | JDBC 类型 |
---|---|---|
BooleanTypeHandler | java.lang.Boolean , boolean | 数据库兼容的 BOOLEAN |
ByteTypeHandler | java.lang.Byte , byte | 数据库兼容的 NUMERIC 或 BYTE |
ShortTypeHandler | java.lang.Short , short | 数据库兼容的 NUMERIC 或 SMALLINT |
IntegerTypeHandler | java.lang.Integer , int | 数据库兼容的 NUMERIC 或 INTEGER |
LongTypeHandler | java.lang.Long , long | 数据库兼容的 NUMERIC 或 BIGINT |
FloatTypeHandler | java.lang.Float , float | 数据库兼容的 NUMERIC 或 FLOAT |
DoubleTypeHandler | java.lang.Double , double | 数据库兼容的 NUMERIC 或 DOUBLE |
BigDecimalTypeHandler | java.math.BigDecimal | 数据库兼容的 NUMERIC 或 DECIMAL |
StringTypeHandler | java.lang.String | CHAR , VARCHAR |
ClobReaderTypeHandler | java.io.Reader | - |
ClobTypeHandler | java.lang.String | CLOB , LONGVARCHAR |
NStringTypeHandler | java.lang.String | NVARCHAR , NCHAR |
NClobTypeHandler | java.lang.String | NCLOB |
BlobInputStreamTypeHandler | java.io.InputStream | - |
ByteArrayTypeHandler | byte[] | 数据库兼容的字节流类型 |
BlobTypeHandler | byte[] | BLOB , LONGVARBINARY |
DateTypeHandler | java.util.Date | TIMESTAMP |
DateOnlyTypeHandler | java.util.Date | DATE |
TimeOnlyTypeHandler | java.util.Date | TIME |
SqlTimestampTypeHandler | java.sql.Timestamp | TIMESTAMP |
SqlDateTypeHandler | java.sql.Date | DATE |
SqlTimeTypeHandler | java.sql.Time | TIME |
ObjectTypeHandler | Any | OTHER 或未指定类型 |
EnumTypeHandler | Enumeration Type | VARCHAR 或任何兼容的字符串类型,用来存储枚举的名称(而不是索引序数值) |
EnumOrdinalTypeHandler | Enumeration Type | 任何兼容的 NUMERIC 或 DOUBLE 类型,用来存储枚举的序数值(而不是名称)。 |
SqlxmlTypeHandler | java.lang.String | SQLXML |
InstantTypeHandler | java.time.Instant | TIMESTAMP |
LocalDateTimeTypeHandler | java.time.LocalDateTime | TIMESTAMP |
LocalDateTypeHandler | java.time.LocalDate | DATE |
LocalTimeTypeHandler | java.time.LocalTime | TIME |
OffsetDateTimeTypeHandler | java.time.OffsetDateTime | TIMESTAMP |
OffsetTimeTypeHandler | java.time.OffsetTime | TIME |
ZonedDateTimeTypeHandler | java.time.ZonedDateTime | TIMESTAMP |
YearTypeHandler | java.time.Year | INTEGER |
MonthTypeHandler | java.time.Month | INTEGER |
YearMonthTypeHandler | java.time.YearMonth | VARCHAR 或 LONGVARCHAR |
JapaneseDateTypeHandler | java.time.chrono.JapaneseDate | DATE |
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映射文件需要满足以下条件
-
接口名与映射文件名相同
-
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>
-
将映射文件与配置文件放在同一文件夹下
测试代码
@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.关于数据库厂商标识
主要目的是为了能在多环境下适配多种数据库