Mybatis框架快速上手
文档地址:
https://github.com/DaweiTian/Note/blob/master/MybatisNote.md
Mybatis是一款优秀的持久层框架,它是用Java语言编写的,它封装了JDBC操作的很多细节,使用了ORM思想实现了结果集的封装,使得开发者只需要关注SQL语句本身,而无需关注注册驱动、创建连接等繁杂过程。
ORM是啥:
Object Relational Mapping 对象关系映射(就是把数据库表和实体类及实体类的属性对应起来让我们可以操作实体类就实现操作数据库表。)
Mybatis的环境搭建(Maven)
第一步:创建maven工程并导入坐标
第二步:创建实体类和Dao接口
第三步:创建Mybatis的主配置文件——MybatisConf.xml(名字自己起)
第四步:创建映射配置文件——IMapper.xml(名字自己起)
Mybatis和mysql-connector等常用的坐标
<!--Mybatis-->
<dependency>
<groupId>org.Mybatis</groupId>
<artifactId>Mybatis</artifactId>
<version>3.5.5</version>
</dependency>
<!--Mysql连接驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
<scope>runtime</scope>
</dependency>
<!--单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!--如果使用的是mysql8.0之后的版本,则应该导入一下的坐标-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
<scope>runtime</scope>
</dependency>
MybatisConf.xml的约束
在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">
IMapper.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">
MybatisConf.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">
<!-- Mybatis 主配置文件 -->
<configuration>
<!-- 配置环境 -->
<environments default="mysql">
<!-- 配置mysql环境 -->
<environment id="mysql">
<!-- 配置事务的类型 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置数据源,也叫连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/使用的数据库名"/>
<property name="username" value="用户名"/>
<property name="password" value="密码"/>
</dataSource>
</environment>
</environments>
<!-- 指定映射配置文件的位置 -->
<mappers>
<mapper resource="top/aerlee/dao/IMapper.xml"/></mappers>
</configuration>
<!--如果使用注解的方式,则mappers部分是下面这样-->
<mappers>
<mapper class="top.aerlee.dao.IDao"/>
</mappers>
IMapper.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="top.aerlee.dao.IDao">
<!--配置sql语句的标签id属性必须和持久层接口中方法的名称一致-->
<select id="showAll" resultType="top.aerlee.domain.Girl">
select * from 数据库表;
</select>
</mapper>
环境搭建的注意事项
I:
IMapper.xml是配置结果映射和SQL语句等相关内容的配置文件,可以根据需要来命名。
II:
在idea中创建目录跟创建包是不一样的,创建包时使用“.”做分隔可以创建三级目录结构,而创建目录时如果使用“.”做分隔指挥创建成一个一级目录。
包(package)在创建时:top.aerlee.dao是三级目录结构
目录(directory)在创建时:top.aerlee.dao是一级目录结果
III:
Mybatis的映射配置文件位置必须和dao接口的包结构相同。
比如,IMapper.xml是IDao.java的映射配置文件,IDao.java放置在
main.java.top.aerlee.dao
包下,那么IMapper.xml文件必须放置在
main.resources.top.aerlee.dao
包下。
**IV:**映射配置文件的mapper标签namespace属性的取值必须是dao接口的全限定类名。
**V:**映射配置文件的操作配置(select标签等),id属性的取值必须是dao接口的方法名
在开发中,当我们遵从了上面的III,IV,V点之后,我们就无须再写dao的实现类,而是使用代理对象即可实现所有功能。
快速入门
在这里,为了演示的效果,建有一个数据库:girlsinfo;数据库中有一张表:girls,girls表有三个属性,id,name,address三个列;一个实体类Girl的三个属性对应着girls表中的三列。一个查询接口:IDao.java,其中包含一个抽象方法 List<Girl> showAll();
// 第一步:获取字节输入流,读取配置文件
InputStream in = Resources.getResourceAsStream("MybatisConf.xml");
// 第二步:创建SqlSessionFactory工厂对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
// 第三步:使用SqlSessionFactory对象生产一个SqlSession对象
SqlSession session = factory.openSession();
// 第四步:创建Dao接口的代理对象
IDao girldao = session.getMapper(IDao.class);
// 第五步:使用代理对象执行dao中的方法
List<Girl> girls = girldao.showAll();
// 第六步:释放资源
session.close();
in.close();
/*
一定要在映射配置中告知Mybatis要封装到哪个实体类中,即resultType属性
配置的方式:指定实体类的全限定类名
*/
模糊查询的两种方式
第一种是在传入参数的时候加上%String%,如:
List<Girl> girls = GirlDao.searchByName("%李%");
这种方式其实是使用了占位符的方式,也就是PrepareStatement。
<select id="searchByName" parameterType="String" resultType="top.aerlee.domain.Girl">
select * from girls where name like #{String}
</select>
第二种是在sql语句中加上‘%’,在传入参数的时候,不需要再添加%,如:
List<Girl> girls = girldao.searchByName("李");
这种方式其实是使用了字符串拼接的方式,也就是Statement。
<select id="searchByName" parameterType="String" resultType="top.aerlee.domain.Girl">
<!--其中value是指定的,必须为value -->
select * from girls where name like '%${value}%'
</select>
在这里,如果使用第二种方式,那么**${value}**中的value这个参数是不能自定义的,因为在源码中绑定了这个关键字为参数。但是一般情况下,从安全等角度来讲,我们还是使用第一种方式多一些。
映射配置文件IMapper.xml中的一些标签及其属性
resultType属性
:用于指定结果集的封装类型,它支持基本类型和实体类型,当使用实体类型且没有注册别名(**
typeAliases
**标签)时,要使用全限定类名来指定,而且同时,如果是使用实体类作为返回类型,则还有一个要求,实体类中的属性名称必须和查询语句中的列名保持一致,否则将无法实现结果的封装。(小提示: MySQL在Windows系统中不区分大小写)
那么如果实体类跟查询语句中的列名不一致的时候如何处理?
1️⃣ 使用别名查询,例如:
SELECT id as girlID,name as girlName FROM girls;
(但这种方法仅适用于列比较少的情况,如果列多的话,那么SQL语句会显得很冗长。)
2️⃣ 定义resultMap标签,将实体类跟数据库表两者之间的映射关系定义在标签中,然后再在select标签中配置resultMap属性。
resultMap属性
:用于定义要封装的实体类属性跟数据库表之间的映射关系。然后再在select标签中配置resultMap属性,替换原来的resultType即可。如:
<select id="showAll" resultMap="该Map的id"> SELECT * FROM girls</select>
<resultMap type="要封装实体类的权限定类名" id="该Map的id,可以指定多个">
<!-- id标签用于指定主键字段-->
<id column="指定数据库列名" property="指定实体类属性名称"/>
<!-- result标签用于指定非主键字段-->
<result column="指定数据库列名1" property="指定实体类属性名称1"/>
<result column="指定数据库列名2" property="指定实体类属性名称2"/>
</resultMap>
parameterType属性
:用于指定传入参数的类型,可以是基本类型 、引用类型、实体类(pojo类)、也可以是实体类的包装类。当使用基本类型和String的时候,可以直接写类型名称或者
包名.类名
的形式,例如:
parameterType=”String”
或者
ParameterType=”java.lang.String”
,当使用实体类的时候,只能使用全限定类名。这是因为Mybatis框架事先已经把基本类型和一些常用的类型注册了别名,而实体类因为是我们自己定义的pojo类,所以没有注册别名,所以只能用全限定类名来找到它们了。
SQL语句中的占位符“#{}”
:相当于原来JDBC中的 “?”,都是用于执行语句时替换实际的数据,具体的数据由#{}中的内容决定。
#{}中内容的怎么写?
:如果是基本数据类型,就随便写,如果是是实体类属性,则写的是实体类对象中的属性名称,使用的是OGNL表达式,它是按照#{对象.对象}的方式来获取数据的。
OGNL表达式:
Object Graphic Navigation Language
对象 图 导航 语言
它是通过对象的取值方法来获取数据。在写法上把get给省略了。
比如:我们获取用户的名称
类中的写法:user.getUsername();
OGNL表达式写法:user.username
selectKey标签
<insert id="saveinfo" parameterType="Girl">
<selectKey keyProperty="id" keyColumn="id" order="AFTER" resultType="int">
select last_insert_id()
</selectKey>
insert into girls(name, address) values(#(name), #{address})
</insert>
它的作用是将SELECT LAST_INSERT_ID()的结果放入传入的Girl的主键(id)里面。
keyProperty属性:是对象中的主键的属性名,这里是Girl中的id,因为它跟数据库的主键对应。
order属性:有两个值,其中AFTER表示
SELECT LAST_INSERT_ID()
在insert执行之后执行,多用于自增主键,得到的值其实是当前要插入的数据对应的主键。BEFORE表示
SELECT LAST_INSERT_ID()
在insert执行之前执行,这样的话就拿不到当前要插入数据的主键了,这种适合那种主键不是自增的类型,得到的值其实是数据库原本记录的最后一个主键的值。
resultType属性:主键的数据类型。
基于自己编写实体类的方式开发Dao层
实际上,在使用Mybatis框架来开发Dao层的时候,我们更常用的是基于接口代理对象的方式,使用代理的方式去开发Dao层会非常的便捷,这在前面的内容里我们已经有所了解了,但是,Mybatis是支持自己写实现类去开发Dao层的,我们在这里做一个简单的了解。
编写接口的实现类
// 之前的接口不变, 另外编写一个IDao接口的实现类
public class DaoImpl implements IDao{
// 定义一个SqlSessionFactory
private SqlSessionFactory factory;
// 编写构造方法,在创建对象的时候传入一个SqlSessionFactory对象
public DaoImpl(SqlSessionFactory factory){
this.factory = factory;
}
// 重写接口中未实现的方法
@Override
public List<Girl> showAll(){
// 通过SqlSessionFactory对象获取一个SqlSession对象
SqlSession session = factory.openSession();
// 调用SqlSession对象的selectList方法,传递方法
List<Girl> girls = session.selectList("top.aerlee.dao.IDao.showAll");
// 关闭SqlSession对象
session.close();
return girls;
}
}
测试实现
//1.获取字节输入流来读取配置文件
InputStream in = Resources.getResourceAsStream("MybatisConf.xml");
//2.创建构建者对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//3.创建 SqlSession 工厂对象
SqlSessionFactory factory = builder.build(in);
//4.创建 Dao 接口的实现类
IDao girldao = new DaoImpl(factory);
// 其实区别就在这里,我们将Session的部分在接口实现类部分完成了,所以这里直接将SqlSessionFactory对象
// 传递给实现类,在实现类部分调用SqlSession的相关方法完成操作,其它部分是一样的。
MybatisConf.xml中的一些配置标签
properties标签——用来配置数据库的连接
其实就是将之前我们MybatisConf.xml中的数据库连接那部分提取了出来。有两种方法来配置properties属性。
第一种是直接将连接属性部分提取出来的方法:
<properties>
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/数据库"/>
<property name="username" value="用户名"/>
<property name="password" value="密码"/>
</properties>
第二种是在ClassPath下定义连接配置文件database.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/数据库(要连接的数据库)
jdbc.username=用户名
jdbc.password=密码
通过properties标签的两个属性:resource或url来指定properties配置文件的位置,如果使用resources属性时,要求配置文件必须在类路径下,一般放在src/main/resources目录下,如:
<properties resource="database.properties"></properties>
如果使用url属性时,则要按照url要求来写。如:
<properties url="file:///F:/IdeaProjects/YourProject/src/main/resources/database.properties"> </properties>
当我们配置了properties标签,那么MybatisConf.xml中的dataSource连接部分就应该这样写:
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name=