MyBatis
学习mybatis必须要了解XML的知识与JDBC的知识。
XML点击学习
JDBC点击学习
介绍MyBatis
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。
Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。
MyBatis的核心框架
上图是来自此乃大佬,我学习的目标。
学习MyBatis可以分为以下几步,个人理解。
- 理解mybatis核心配置文件
- 理解Mapper XML配置文件
- 创建工厂使用Mapper中的增删改查方法
- 通过接口与Mapper中的sql语句自动生成接口的实现类
- 使用注解自动完成4操作
1. 理解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">
一些标签的简单注解详情看api:
标签名 | 作用 |
---|---|
configuration | 配置文件根目录 |
properties | 这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置。 |
settings | 这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。 |
typeAliases | 类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。 |
typeHandlers | MyBatis 在设置预处理语句(PreparedStatement)中的参数或从结果集中取出一个值时, 都会用类型处理器将获取到的值以合适的方式转换成 Java 类型。下表描述了一些默认的类型处理器。 |
objectFactroy | 每次 MyBatis 创建结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成实例化工作。 默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认无参构造方法,要么通过存在的参数映射来调用带有参数的构造方法。 如果想覆盖对象工厂的默认行为,可以通过创建自己的对象工厂来实现。 |
plugins | MyBatis 允许你在映射语句执行过程中的某一点进行拦截调用。 |
environments | MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中, 现实情况下有多种理由需要这么做。例如,开发、测试和生产环境需要有不同的配置;或者想在具有相同 Schema 的多个生产数据库中使用相同的 SQL 映射。还有许多类似的使用场景。 |
databaseidProvider | MyBatis 可以根据不同的数据库厂商执行不同的语句,这种多厂商的支持是基于映射语句中的 databaseId 属性。 MyBatis 会加载带有匹配当前数据库 databaseId 属性和所有不带 databaseId 属性的语句。 如果同时找到带有 databaseId 和不带 databaseId 的相同语句,则后者会被舍弃。 为支持多厂商特性,只要像下面这样在 mybatis-config.xml 文件中加入 databaseIdProvider 即可 |
mappers | 既然 MyBatis 的行为已经由上述元素配置完了,我们现在就要来定义 SQL 映射语句了。 但首先,我们需要告诉 MyBatis 到哪里去找到这些语句。 在自动查找资源方面,Java 并没有提供一个很好的解决方案,所以最好的办法是直接告诉 MyBatis 到哪里去找映射文件。 |
简单配置:
<?xml version="1.0" encoding="UTF-8" ?>
<!--dtd: 规定mybatis核心配置稳定的定义要求:内容,位置,规范...-->
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--基础核心配置 : 根元素-->
<configuration>
<!--使用的环境: 定义事务管理,数据库连接,连接参数配置...-->
<!--
environments: 可以定义多个环境environment
default : 选择使用哪一个环境,关联environment的id 属性值
-->
<environments default="dvd">
<!--定义环境基础配置: id: 表示唯一 不可重复-->
<environment id="dvd">
<!--事务管理: type="JDBC" 使用JDBC的事务管理机制-->
<transactionManager type="JDBC"/>
<!--数据源的配置: type="POOLED" 选择使用数据库连接池管理连接 -->
<dataSource type="POOLED">
<!--配置连接参数 name:配置的内容 value:数据值 -->
<property name="driver" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@localhost:1521:XE"/>
<property name="username" value="SCOTT"/>
<property name="password" value="TIGER"/>
</dataSource>
</environment>
</environments>
<!--配置sql映射文件的位置-->
<mappers>
<mapper resource="com/xxxx/mappers/DeptMapper.xml"/>
</mappers>
</configuration>
2 . 理解Mapper 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">
常用的一些标签
标签名 | 作用 |
---|---|
cache | 配置给定命名空间的缓存。 |
cache-ref | 从其他命名空间引用缓存配置。 |
resultMap | 最复杂,也是最有力量的元素,用来描述如何从数据库结果集中来加 载你的对象。 |
sql | 可以重用的 SQL 块,也可以被其他语句引用。 |
insert | 映射插入语句 |
update | 映射更新语句 |
delete | 映射删除语句 |
select | 映射查询语句 |
常用的标签属性 增删改查中
属性名 | 作用 |
---|---|
parameterType | 传入参数形式 |
resultType | 结果参数形式 |
理解:两端说明数据类型,这样传入数据与传出数据格式就可以确定,就可以使传出与传入格式匹配到,做到数据自动匹配,读取,与存出。
#{}与${}的区别需要区别
#{}方式能够很大程度防止sql注入(安全),${}方式无法防止Sql注入。
简单模板
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--
SQL映射文件 mapper 根元素映射配置
namespace: 命名空间 必填
在当前项目下是唯一的,唯一标识,标识sql映射文件的唯一
任意定义,内容没有要求
一般定义为:当前sql映射文件的包名.文件名 com.xxxx.mappers.DeptMapper
-->
<mapper namespace="ppl.com.mapper.DeptMapper">
<!--
select : 定义查询语句
id : 是当前命名空间下的sql语句的唯一标识,当前命名空间下不能重复
resultType : 结果类型
常用的结果类型: 基本数据类型 包装类型 String Date Javabean List Map.
parameterType : 入参类型
常用的入参类型: 基本数据类型 包装类型 String Date Javabean List 数组 Map
-->
<select id="queryAll" resultType="String">
select dname from dept
</select>
<select id="queryAllDept" resultType="ppl.com.pojo.Dept">
select * from dept
</select>
<select id="deptByNo" resultType="ppl.com.pojo.Dept">
select * from dept where deptno= #{deptno}
</select>
</mapper>
3. 创建工厂使用Mapper中的增删改查方法
简单步骤:
- 创建SqlSessionFactoryBuilder对象
- 加载SqlMapConfig.xml配置文件
- 创建SqlSessionFactory对象
- 创建SqlSession对象
- 通过SqlSession对象调用Mapper中的增删改查方法
了解SqlSession类
大概分为三种:selectOne selectList selectMap 重载方法。
selectOne(sql=sql语句的id值定位到方法) 返回一个结果对象 resultType形式
selectList(sql) 返回结果列表对象 resultType形式
selectOne(String var1, Object var2) 传入一个parameterType形式 返回一个resultType形式
<K, V> Map<K, V> selectMap(String var1, Object var2, String var3); var3指传入结果resultType一个属性作为主键。
public interface SqlSession extends Closeable {
<T> T selectOne(String var1);
<T> T selectOne(String var1, Object var2);
<E> List<E> selectList(String var1);
<E> List<E> selectList(String var1, Object var2);
<E> List<E> selectList(String var1, Object var2, RowBounds var3);
<K, V> Map<K, V> selectMap(String var1, String var2);
<K, V> Map<K, V> selectMap(String var1, Object var2, String var3);
<K, V> Map<K, V> selectMap(String var1, Object var2, String var3, RowBounds var4);
<T> Cursor<T> selectCursor(String var1);
<T> Cursor<T> selectCursor(String var1, Object var2);
<T> Cursor<T> selectCursor(String var1, Object var2, RowBounds var3);
void select(String var1, Object var2, ResultHandler var3);
void select(String var1, ResultHandler var2);
void select(String var1, Object var2, RowBounds var3, ResultHandler var4);
int insert(String var1);
int insert(String var1, Object var2);
int update(String var1);
int update(String var1, Object var2);
int delete(String var1);
int delete(String var1, Object var2);
void commit();
void commit(boolean var1);
void rollback();
void rollback(boolean var1);
List<BatchResult> flushStatements();
void close();
void clearCache();
Configuration getConfiguration();
<T> T getMapper(Class<T> var1);
Connection getConnection();
}
案例:
public class Test {
public static void main(String[] args) throws IOException {
// 1. 创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 2. 加载SqlMapConfig.xml配置文件
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
// 3. 创建SqlSessionFactory对象
this.sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
// 4. 使用工厂生产SqlSession对象
SqlSession session=factory.openSession();
List<String> list = session.selectList("ppl.com.mapper.DeptMapper.queryAll");
System.out.println(list);
Dept dept = session.selectOne("ppl.com.mapper.DeptMapper.deptByNo", 30);
System.out.println(dept);
Map<Integer, Dept> deptno = session.selectMap("ppl.com.mapper.DeptMapper.queryAllDept", "deptNo");
System.out.println(deptno);
session.close();
in.close();
}
}
4. 通过接口与Mapper中的sql语句自动生成接口的实现类
首先将接口与Mapper写在同一个包下,然后命名相同。
MapperEmp接口:
public interface MapperEmp {
/**
* 查询所有的Emp表
* @return
*/
List<Emp> findAllEmp();
}
MapperEmp.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="ppl.com.mapper.MapperEmp">
<select id="findAllEmp" resultType="ppl.com.pojoEmp">
select * from emp
</select>
</mapper>
Test 使用方法
public class Test {
public static void main(String[] args) throws IOException {
InputStream is = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(is);
SqlSession sqlSession = factory.openSession();
List<Emp> list = sqlSession.selectList("ppl.com.mapper.MapperEmp.findAllEmp");
list.forEach(System.out::println);
//这个使用的方法
MapperEmp mapper = sqlSession.getMapper(MapperEmp.class);
System.out.println("MapperEmp.class:"+MapperEmp.class);
List<Emp> allEmp = mapper.findAllEmp();
allEmp.forEach(System.out::println);
}
}
下图是个人的理解:
5. 使用注解自动完成4操作
public interface MapperAu {
@Select("select * from emp where ename=#{name}")
List<Emp> selectAll(String name);
}