什么是MyBatis?
MyBatis是一个优秀的持久层框架(就是将某些数据持久化到硬盘或其他存储器中的框架),它把jdbc对数据库的操作进行了封装,使用户只需关注sql本身,不需要去执行jdbc的那一套复杂的操作。
MyBatis通过配置xml文件或注解的方式,将statement或preparedstatement中的sql语句与java对象中的数据相互映射,最终生成可执行的sql语句,由MyBatis执行sql语句,并将返回结果封装成java对象。
简而言之,MyBatis封装了JDBC对数据库的复杂操作,并将返回结果封装成所需的java对象。
MyBatis流程图:
1.MyBatis-config.xml文件是MyBatis的核心配置文件,这个文件中配置了运行环境,事务管理方式,是否使用连接池等,MyBatis可以通过该配置文件创建SqlSessionFactory
2.SqlSessionFactory用来创建SqlSession
3.SqlSession是用来发送sql语句到数据库执行,并返回结果,类似于jdbc中的connection
4.executor是MyBatis的一个底层对象,用于执行sql语句
5.MapperStatement也是MyBatis的一个底层对象,用于将配置文件中的sql语句映射为可执行的sql语句。
JDBC与MyBatis的对比
JDBC:
1.使用jdbc有大量重复且复杂的代码
2.jdbc中的sql语句是写死在代码中,一旦修改sql还需重新编译代码
3.jdbc本身是不支持使用连接池的,会不断的创建连接,释放资源,影响效率
4.jdbc返回的ResultSet对象,需要我们手动处理,特别麻烦
MyBatis:
1.MyBatis对JDBC进行了封装,可以简化了代码
2.MyBatis的sql语句都是写在配置文件中的,如需修改sql,修改配置文件即可
3.MyBatis本身是支持连接池的,且MyBatis还可以兼容其他连接池
4.MyBatis会将返回的结果,封装为相应的java对象,极大的减少了我们的麻烦。
MyBatis的用法
1.首先导入MyBatis框架的所需依赖
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.2.8</version>
</dependency>
2.配置MyBatis的核心配置文件,MyBatis-config.xml
1)配置头文件
<?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">
<!-- MyBatis的全局配置文件 -->
<configuration >
</configuration>
第一行是xml文档的声明,及使用的编码
第2,3,4行用来引入xml文件的约束文档,该文档受mybatis-3-config.dtd的约束
mybatis的环境配置都是在configuration中进行配置的。
2)配置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">
<!-- MyBatis的全局配置文件 -->
<configuration >
<environments default="develop">
<environment id="develop">
<!--配置事务管理方式,MANAGED/JDBC
MANAGED:自己管理
JDBC:由JDBC进行管理(推荐)
-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据库连接方式,POOLED/UNPOOLED/JNDI
JNDI:已过时
UNPOOLED:不使用连接池
POOLED:使用连接池
-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/yonghedb?characterEncoding=utf-8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper>
<mapper resource="EmpMapper.xml"/>
</mapper>
</mappers>
</configuration>
environments,mybatis中可以同时部署多套环境,都是配置在environments,通过environments标签中的default属性来切换环境。
environment,mybatis中的环境配置,每个environment都有一个id,environments通过这个id来切换环境
transactionManager,数据库事务管理方式,由MANAGED/JDBC两种,MANAGED,自己手动管理事务,JDBC,由jdbc来管理事务
datasource,数据源,这里配置数据库连接是否使用连接池,JNDI/POOLED/UNPOOLED
mappers,可以在该标签下配置多个mapper
mapper,每个mapper对应一个mapper.xml配置文件
3.创建对应表的mapper.xml文件,并将该映射文件配置到MyBatis-config.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值应该保证唯一
在程序中通过[ namespace + id ]定位到要执行哪一条SQL语句
-->
<mapper namespace="EmpMapper">
<!-- 通过select、insert、update、delete标签声明要执行的SQL -->
<!-- 练习1: 查询emp表中的所有员工信息
resultType指定查询的结果将会封装到什么类型中
即使最终返回的结果是集合(List<Emp>),resultType也只需要指定集合中的泛型即可!
-->
<select id="findAll" resultType="com.tedu.pojo.Emp">
select * from emp
</select>
</mapper>
mapper,根标签,其中namespace(命名空间,要求不能重复),通过namespace+id来定位一条sql语句
select,映射文件中配置的sql类型标签
id,一条sql语句的标识
resultType,sql执行返回的结果类型,如果返回的是一个集合,那么这里包含的应该是集合的泛型,例如上述sql返回结果为list
则这里resultType就是泛型emp的全限定类名
resultMap,复杂对象结构,常用与多表查询,resultType与resultMap不能同时使用
4.通过Java代码查询数据库中数据
public class TestMyBatis(){
public void main(String args[]){
//1.读取MyBatis-config.xml核心配置文件
InputStream in=Resources.getResourceAsStream("mybatis-config.xml");
//2.创建SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(in);
//3.创建Sqlsession对象
SqlSession sqlSession=sqlSessionFactory.openSession();
//4.执行sql语句
List<emp> empList = sqlSession.selectList("emp.findAll");
//5.对返回结果进行操作
for (emp item:empList) {
System.out.println(item.toString());
}
}
}
MyBatis中的占位符#{}和${}
${}和#{}的区别:
‘#{}’相当与jdbc中的?,并会将传进来的字符进行转义处理,在字符的两边加上单引号。
‘${}’是直接将传进来的字符拼接到sql中的,因此有可能出现sql注入,所以每个${}传进来的值,都需进行封装,即使只有一个值。
动态sql标签
标签‘
<!--
* 如果没有参数, 则不执行where子句, 默认查询所有员工:
* select * from emp
* 如果参数中只有minSal(即minSal不为null), 则:
* ... where salary > minSal
* 如果参数中只有maxSal(即maxSal不为null), 则:
* ... where salary < maxSal
* 如果参数有 minSal、maxSal(即minSal、maxSal不为null), 则:
* ... where salary > minSal and salary < maxSal -->
<select id="findAllBySal" resultType="com.tedu.pojo.Emp">
select * from emp
where 1=1
<if test="minSal != null">
and salary>#{minSal}
</if>
<if test="maxSal != null">
and salary <![CDATA[ < ]]> #{maxSal}
</if>
</select>
根据if标签中的test属性,来判断是否拼接if标签中的sql
注意sql中的 ‘where 1==1‘,这是为了防止第一个if中的and
标签‘
<!--
* 如果没有参数, 则不执行where子句, 默认查询所有员工:
* select * from emp
* 如果参数中只有minSal(即minSal不为null), 则:
* ... where salary > minSal
* 如果参数中只有maxSal(即maxSal不为null), 则:
* ... where salary < maxSal
* 如果参数有 minSal、maxSal(即minSal、maxSal不为null), 则:
* ... where salary > minSal and salary < maxSal -->
<select id="findAllBySal2" resultType="com.tedu.pojo.Emp">
select * from emp
<where>
<if test="minSal != null">
and salary>#{minSal}
</if>
<if test="maxSal != null">
and salary <![CDATA[ < ]]> #{maxSal}
</if>
</where>
</select>
where标签会在需要的时候生成where语句,并且会剔除多余的and或or,例如本例中若第一个if成立就会生成where并剔除and
标签‘
这个标签主要用于遍历集合
<!--
delete from emp where id in (1,3,5,7)
collection: 如果传的参数仅仅是一个数组或者List集合, collection可以指定为
array或list; 如果传的是多个参数,用map封装,collection则指定为map中的key
open: 指定生成的SQL片段以什么符号开始
close: 指定生成的SQL片段以什么符号结束
item: 指定变量接收数组或集合中的元素
separator: 指定一个间隔符, 在将数组或集合中的每个元素拼接到SQL片段之后,
在后面拼接一个间隔符
-->
<delete id="deleteByIds">
delete from emp where id in
<foreach collection="array" open="(" item="id" separator="," close=")">
#{id}
</foreach>
</delete>
foreach标签中的属性
collection 集合(必需)
item 集合中的元素(必需)
open 以什么开始
close 以什么结束
separator 集合中元素的分割符
MyBatis的接口开发
上述,在Java代码中查询数据库时,是通过namepace+id定位sql的,mybatis还有一个更简单的方法来定位sql,通过接口中的方法直接定位到sql
要求:
1.创建一个接口,再创建mapper映射文件,映射文件中的namespace与接口的全限定类名一致
2.mapper映射文件中的每条sql,接口中都需要有一个对应的方法
3.接口中方法的入参类型要与sql中接收的参数类型一致
4.接口中方法的返回值类型要与sql中resultType中的一致(注意resutType中只是泛型)