目录
一、概述
二、Mybatis案例
1.项目结构
2.修改pom文件,添加mybatis的jar包依赖
3.创建核心配置文件,指定连接数据库的参数
4.创建映射文件,写SQL
5.创建User类
6.创建测试类
三、其它知识点
1.别名
2.xml的转义符号
3.参数值:paramterType
4.返回值:resultType
5.返回值:resultMap
6.#和$的区别
7.sql和include
8.if
9.where
10.set
11.foreach
?四、动态SQL
1.需求
2.创建Dept类,用来完成ORM
3.创建DeptMapper.xml,用来写SQL
4.修改核心配置文件,引用新的映射文件
5.创建测试文件
五、Mybatis的接口开发
1.结构
2.修改映射文件,把namespace的值改成接口的全路径
3.创建接口文件
4.测试类
六、ResultMap
1.概述
2.测试
七、优化简化resultmap
八、SpringBoot 整合Mybatis流程
九、Mybatis调用流程
一、概述
简化了JDBC操作数据库的过程,是一个优秀的ORM框架。 两个配置文件: 核心配置文件 – 用来配置数据库的连接的参数(例:mybatis-config.xml) 映射文件 – 用来写SQL(例:UserMapper.xml) 两个核心的工具类: SqlSessionFactory – 会话工厂,用来产生会话 SqlSession – 会话,用来执行SQL ORM:对象关系映射 是指把表里字段的值 自动映射给 类里的属性
二、Mybatis案例
1.项目结构
?
2.修改pom文件,添加mybatis的jar包依赖
<dependencies>
<!--mybatis依赖包-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<!--jdbc依赖包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.48</version>
</dependency>
</dependencies>
3.创建核心配置文件,指定连接数据库的参数
<?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>
<!--可以配置多个数据库连接的环境,使用default指定默认用哪个-->
<environments default="test">
<!--配置了具体连接数据库的参数-->
<environment id="test">
<!--使用的事务管理器-->
<transactionManager type="JDBC"></transactionManager>
<!--数据源:就是制定了数据库连接时的参数-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatisdb2?characterEncoding=utf8&serverTimezone=Asia/Shanghai" />
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--引入映射文件-->
<mappers>
<mapper resource="UserMapper.xml"></mapper>
</mappers>
</configuration>
4.创建映射文件,写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">
<!--这是映射文件,namespace用来作为文件的唯一标识
-->
<mapper namespace="UserMapperNS">
<!--select标签表示要发起查询的SQL,
id是SQL语句的唯一标识,
resultType用来完成ORM,把表里的字段值 自动映射 类里的属性
-->
<select id="getAll" resultType="cn.tedu.pojo.User">
select * from user
</select>
</mapper>
5.创建User类
package cn.tedu.pojo;
//Mybatis自动完成ORM,把表里的字段的值 查到 封装给 类里的属性
//要求:属性名要和字段名一样
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private Integer id;
private String name;
private String addr;
private Integer age;
}
6.创建测试类
public class Test1 {
@Test
public void get() throws IOException {
//1,读取核心配置文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//2,创建会话工厂
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//3,创建会话
SqlSession session = factory.openSession();
//4,执行SQL
//session.selectList("namespace的值.id的值");//唯一的定位了SQL
List<User> list = session.selectList("UserMapperNS.getAll");//查询出多个结果
//5,处理结果
for(User u : list){
System.out.println(u);
}
}
}
三、其它知识点
1.别名
–设置别名:修改核心配置文件,加一个typeAliases标签
<!--用来设置别名 type是类的全路径 alias是以后要用的别名-->
<typeAliases>
<typeAlias type="cn.tedu.pojo.User" alias="User"></typeAlias>
</typeAliases>
–使用别名:在映射文件里,在resultType处直接使用别名
<select id="getAll" resultType="User">
select * from user
</select>
2.xml的转义符号
3.参数值:paramterType
指定参数类型,通常制定一个对象类型。
4.返回值:resultType
完成ORM的映射关系所在。这里指定的cd.tedu.mybatis.domain.User代表把结果集转换成一个User对象实例。
5.返回值:resultMap
resultMap 用于对复杂对象结构时,对应的ResultMap结构名称
6.#和$的区别
两种方式都可以获取参数的值。区别如下:
#: 使用#{parameterName}引用参数的时候,Mybatis会把这个参数认为是一个字符串,例如传入参数是"Smith",那么在SQL(Select * from emp where name = #{employeeName})使用的时候就会转换为Select * from emp where name = 'Smith'。
$: 不做字符串拼接,SQL(Select * from emp where name = ${employeeName})使用的时候就会转换为Select * from emp where name = Smith。此时,如果字段是varchar类型直接抛出SQL异常。(如果where后输入1=1,也能获取要获取的信息,存在注入安全隐患)
!!!从安全性上考虑,能使用#尽量使用#来传参,因为这样可以有效防止SQL注入的问题。
7.sql和include
Sql标签用来提取SQL片段,来提高SQL的复用.
使用位置需要通过include引用指定的SQL片段.
<sql id="cols">
id,title,sell_point,price,num,barcode,image,cid,status,created,updated
</sql>
<select id="find" resultType="Item" parameterType="Item">
SELECT <include refid="cols"/> FROM tb_item
</select>
8.if
执行SQL时,可以添加一些判断条件.
<select id="find" resultType="Item" parameterType="Item">
SELECT <include refid="cols"/> FROM tb_item where
<if test="title != null"> title like #{title} </if>
<if test="sellPoint != null">and sell_point like #{sellPoint}</if>
</select>
9.where
去掉条件中可能多余的and或者or:
<select id="find" resultType="Item" parameterType="Item">
SELECT <include refid="cols"/> FROM tb_item
<where>
<if test="title != null"> title like #{title} </if>
<if test="sellPoint != null">and sell_point like #{sellPoint}</if>
</where>
</select>
10.set
去掉最后可能多余的逗号:
<update id="update">
UPDATE teachers
<set>
<if test="tname != null">tname=#{tname},</if>
<if test="tsex != null">tsex=#{tsex},</if>
<if test="tbirthday != null">tbirthday=#{tbirthday},</if>
<if test="prof != null">prof=#{prof},</if>
<if test="depart != null">depart=#{depart}</if>
</set>
WHERE tno=#{tno}
</update>
11.foreach
用于in子查询中的多个值的遍历:
<delete id="delete">
DELETE FROM teachers WHERE tno IN
<!--ids是给SQL传递的参数Map里的key,item的值就像是for循环里的i变量名-->
<foreach collection="ids" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</delete>
调用代码:
Map<String,Object> map = new HashMap<String,Object>();
String[] ps = {"1","22"};
map.put("ids", ps );
mapper.delete(map);
?四、动态SQL
1.需求
操作dept表
2.创建Dept类,用来完成ORM
package cn.tedu.pojo;
//Mybatis自动完成ORM,把表里的字段的值 查到 封装给 类里的属性
//要求:属性名要和字段名一样
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Dept {
private Integer id;
private String dname;
private String loc;
}
3.创建DeptMapper.xml,用来写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">
<mapper namespace="DeptMapperNS">
<!-- 1. 提取SQL片段,提高复用性-->
<sql id="cols">
id,dname,loc
</sql>
<!--resultType使用了别名,因为在核心配置文件里配过了 -->
<select id="getAll" resultType="Dept">
select
<include refid="cols"></include> /* 2.使用了指定的SQL片段*/
from dept;
</select>
<!--查询name=java教研部 的部门信息-->
<select id="getByName" resultType="Dept">
select
<include refid="cols"></include>
from dept
/* if用来判断,test写判断条件,满足条件才执行,不满足不执行*/
<if test="dname != null">
where dname = #{dname}
</if>
</select>
<!--查询id是1或者是3的部门信息
/* 可以去除条件中多余的or 或者 and关键字 */
-->
<select id="getByIds" resultType="Dept">
select
<include refid="cols"></include>
from dept
<where>
<if test="id!=null">
id=#{id}
</if>
or id=3
</where>
</select>
<!--删除id是1 2 3 的部门信息-->
<delete id="delByIds">
/*delete from dept where id in(1,2,3) 参数写死了,最好动态解析*/
delete from dept where id in(
/*foreach用来遍历,collection属性的值是固定值array list map里的key
item相当于遍历得到的数据 separator是数据间的分隔符
*/
<foreach collection="array" item="i" separator="," >
#{i} /*获取了遍历得到的数据*/
</foreach>
)
</delete>
</mapper>
4.修改核心配置文件,引用新的映射文件
<?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>
<!--用来设置别名 type是类的全路径 alias是以后要用的别名-->
<typeAliases>
<typeAlias type="cn.tedu.pojo.Dept" alias="Dept"></typeAlias>
</typeAliases>
<!--可以配置多个数据库连接的环境,使用default指定默认用哪个-->
<environments default="test">
<!--配置了具体连接数据库的参数-->
<environment id="test">
<!--使用的事务管理器-->
<transactionManager type="JDBC"></transactionManager>
<!--数据源:就是制定了数据库连接时的参数-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatisdb2?characterEncoding=utf8&serverTimezone=Asia/Shanghai" />
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--引入映射文件-->
<mappers>
<mapper resource="DeptMapper.xml"></mapper>
</mappers>
</configuration>
5.创建测试文件
public class Test1 {
@Test
public void get() throws IOException {
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
SqlSession session = factory.openSession();
//执行SQL
List<Dept> list = session.selectList("DeptMapperNS.getAll");
for (Dept d : list) {
System.out.println(d);
}
//Mybatis的以及缓存:相同的SqlSession执行相同的SQL时会查缓存不会再次发起SQL了
List<Dept> list2 = session.selectList("DeptMapperNS.getAll");
for (Dept d : list2) {
System.out.println(d);
}
//selectList(1,2)--1是SQL的定位2是SQL需要的参数
List<Dept> list1 = session.selectList("DeptMapperNS.getByName", null);
for (Dept d : list1) {
System.out.println(d);
}
//selectList(1,2)--1是SQL的定位2是SQL需要的参数
List<Dept> list3 = session.selectList("DeptMapperNS.getByIds",null);
for (Dept d : list3) {
System.out.println(d);
}
int[] a = {1,2,3};
session.delete("DeptMapperNS.delByIds",a);//给SQL传入多个参数
//Mybatis不会自动提交事务,需要手动提交:openSession(true)或者commit()
session.commit();//增删改都需要提交事务,不然对数据库没有持久性的影响
System.out.println("删掉了");
}
}
五、Mybatis的接口开发
1.结构
2.修改映射文件,把namespace的值改成接口的全路径
<?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="cn.tedu.dao.DeptDao">
<!-- 1. 提取SQL片段,提高复用性-->
<sql id="cols">
id,dname,loc
</sql>
<!--resultType使用了别名,因为在核心配置文件里配过了 -->
<!--查询name=java教研部 的部门信息-->
<select id="getByName" resultType="Dept">
select
<include refid="cols"></include>
from dept
/* if用来判断,test写判断条件,满足条件才执行,不满足不执行*/
<if test="dname != null">
where dname = #{dname}
</if>
</select>
</mapper>
3.创建接口文件
接口文件的全路径 = Mapper.xml里namespace的值 接口中的方法名 = Mapper.xml里的SQL的id值 接口中的方法的返回值 = Mapper.xml里的SQL的resultType值
package cn.tedu.dao;
//接口文件的全路径 = Mapper.xml里namespace的值
public interface DeptDao {
/**
* 获取所有
* @return 所有部门信息
*/
List<Dept> getAll();
/**
* 根据名称获取部门信息
* @return 相关名字的部门信息
*/
List<Dept> getByName(String name);
List<Dept> getByIds(int[] id);
void delByIds(int[] ids);
}
4.测试类
public class Test2 {
@Test
public void get() throws IOException {
//加载核心配置文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//创建会话工厂
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//创建会话
SqlSession session = factory.openSession();
//获取指定的接口
DeptDao dao = session.getMapper(DeptDao.class);
//调用接口里的方法
List<Dept> list = dao.getAll();
for (Dept dept : list) {
System.out.println(dept);
}
//根据名称获取部门信息
List<Dept> list2 = dao.getByName("开发");
for (Dept dept : list2) {
System.out.println(dept);
}
}
}
六、ResultMap
1.概述
resultType只能完成简单的ORM,只能完成那些 字段名 和 属性名一致的情况 字段名 和 属性名 不一样的情况,resultType必须换成resultMap,否则无法ORM
2.测试
(1)项目结构
(2)创建了表,加了记录
CREATE TABLE `user_info` (
`id` int(11) NOT NULL auto_increment,
`user_name` varchar(20) default NULL,
`user_addr` varchar(20) default NULL,
`user_age` int(11) default NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
(3)修改pom文件,添加mybatis的jar包(略)
(4)创建核心配置文件
<?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指定默认的环境-->
<environments default="test">
<environment id="test">
<!--使用的事务管理器-->
<transactionManager type="JDBC"></transactionManager>
<!--配置了数据源-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatisdb2?characterEncoding=utf8&serverTimezone=Asia/Shanghai" />
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--引入映射文件-->
<mappers>
<mapper resource="userInfoMapper.xml"></mapper>
</mappers>
</configuration>
(5)创建映射文件
<?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="cn.tedu.dao.UserInfoMapper">
<!-- 查询所有 ,字段名和属性名不一样,resultType换成resultMap
resultType="cn.tedu.pojo.UserInfo"
-->
<!-- ORM:是指把字段的值查到以后 交给 同名属性保存
使用resultMap: 字段名 和 属性名 不一样
id是唯一标识 type是类的全路径
-->
<resultMap id="abc" type="cn.tedu.pojo.UserInfo">
<result column="user_name" property="userName"></result>
<result column="user_addr" property="userAddr"></result>
<result column="user_age" property="userAge"></result>
</resultMap>
<!--resultMap属性是解决了resultType解决不了的问题,引用指定的resultMap-->
<select id="selectList" resultMap="abc">
select * from user_info
</select>
</mapper>
?(6)创建接口类
package cn.tedu.dao;
import cn.tedu.pojo.UserInfo;
import java.util.List;
public interface UserInfoMapper {
List<UserInfo> selectList();//查询所有
}
?(7)创建pojo类
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class UserInfo {
private Integer id;
private String userName;
private String userAddr;
private Integer userAge;
}
(8)测试
public class Test1 {
@Test
public void all() throws IOException {
InputStream in = Resources.getResourceAsStream(
"mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder()
.build(in);
//true表示自动提交事务
SqlSession session = factory.openSession(true);
//获取指定接口
UserInfoMapper mapper = session.getMapper(UserInfoMapper.class);
//调用方法
List<UserInfo> list = mapper.selectList();
for (UserInfo uf : list) {
//UserInfo(id=1, userName=null, userAddr=null, userAge=null)
System.out.println(uf);
}
}
}
七、优化简化resultmap
第一步:在核心配置文件中开启驼峰规则
<settings>
<!--开启驼峰规则,简化resultMap的编写-->
<setting name="mapUnderscoreToCamelCase" value="true" />
</settings>
?第二步:resultMap标签中添加新属性 autoMapping=“true”?是开启了自动驼峰规则的匹配
<?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="cn.tedu.dao.UserInfoMapper">
<!-- 查询所有 ,字段名和属性名不一样,resultType换成resultMap
resultType="cn.tedu.pojo.UserInfo"
-->
<!-- ORM:是指把字段的值查到以后 交给 同名属性保存
使用resultMap: 字段名 和 属性名 不一样
id是唯一标识 type是类的全路径
autoMapping="true"是开启了自动驼峰规则的匹配
-->
<resultMap autoMapping="true" id="abc" type="cn.tedu.pojo.UserInfo">
<!-- <result column="user_name" property="userName"></result>
<result column="user_addr" property="userAddr"></result>
<result column="user_age" property="userAge"></result>-->
</resultMap>
<!--resultMap属性是解决了resultType解决不了的问题,引用指定的resultMap-->
<select id="selectList" resultMap="abc">
select * from user_info
</select>
</mapper>
八、SpringBoot 整合Mybatis流程
(1)导入依赖jar包 数据库驱动/JDBC包/Spring整合Mybatis包
(2)编辑application.yml文件 配置数据源/配置Spring整合Mybatis
(3)编辑Mybatis 接口文件/编辑xxx.xml映射文件
(4)通过@MapperScan为接口创建代理对象
九、Mybatis调用流程
(1)Spring容器为接口创建代理对象. Spring容器启动对象立即创建
(2)根据 @Autowired 注解动态注入Mapper接口的代理对象
(3)用户通过Mapper接口调用方法.(执行业务操作)
(4)Mybatis根据接口方法动态匹配xml的映射文件:
? ? ? ? ? 1.根据Mapper的接口路径匹配xml映射文件中的 com.jt.mapper.UserMapper ? ? ? ? ? 2.根据接口的方法 匹配xml映射文件中的Sql ID 之后执行Sql语句
(5)Mybatis将结果集封装为对象 之后返回.
|