MyBatis基础回顾及高级应用
一、MyBatis相关概念回顾
1.对象/关系数据库映射(ORM)
ORM 全称Object Relation Mapping : 表示对象-关系映射的缩写
ORM 完成面向对象的编程语言到关系数据库的映射,它把关系数据库包装成面向对象的模型。采用ORM框架后,应用程序不再直接访问底层数据库,而是以面向对象的方式来操作持久化对象,ORM将把这些对象的操作转换成底层SQL操作。
2.MyBatis简介
- MyBatis是一款优秀的基于ORM的半自动的轻量级的持久层框架,它支持定制化SQL以及高级映射。它避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。
- MyBatis可以使用简单的XML或者注解来配置和映射原生类型、接口和Java的POJO成数据库中的记录。
3.MyBatis历史
- 它原是apache的一个开源项目iBatis,于2010年6月由apache迁移到了google,iBatis3.x正式更名为MyBatis,代码于2013年11月迁移到GitHub。
- iBatis一词来源于"internet"和"abatis"的组合,是一个基于JAVA的持久层框架。它包括SQL Maps和Data Access Objects(DAO)
4.MyBatis优势
- MyBatis是一个半自动的持久层框架,对于开发人员来说,核心的sql还是需要自己进行优化。
- sql和java的编码进行了分离,功能边界更清晰,一个专注业务,一个专注数据。
- 全自动框架生成的sql不易进行优化。当bean字段很多时,无法做到只映射部分字段。
二、MyBatis环境搭建回顾
1.开发步骤
- 引入myBatis的maven坐标
- 创建数据库表
- 创建实体类
- 编写映射文件xxxMapper.xml
- 编写核心配置文件sqlMapConfig.xml
2.环境搭建
- 在pom中添加需要用到的jar包
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!-- mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.22</version>
</dependency>
<!-- junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
<version>2.2</version>
<scope>test</scope>
</dependency>
</dependencies>
- 创建数据库user表并添加数据
create table user
(
id int null,
username varchar(20) default ''
);
insert into user (id,username) values (1,'zhangsan');
insert into user (id,username) values (2,'lisi');
- 创建User实体类
package com.lagou.pojo;
public class User {
private Integer id;
private String username;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
'}';
}
}
- 编写userMapper.xml
sql的唯一id = namespace+id
<?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="user">
<select id="findAll" resultType="com.lagou.pojo.User">
select * from user
</select>
</mapper>
- 编写sqlMapConfig.xml
<!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 事务管理交由JDBC进行处理-->
<transactionManager type="JDBC"/>
<!-- POOLED 使用mybatis的连接池-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///zdy_mybatis"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!-- mapper配置 -->
<mappers>
<mapper resource="UserMapper.xml"/>
</mappers>
</configuration>
- 编写测试类
package con.lagou;
import com.lagou.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class MyBatisTest {
@Test
public void testMybatis() throws IOException {
InputStream stream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(stream);
SqlSession sqlSession = sqlSessionFactory.openSession();
List<User> userList = sqlSession.selectList("user.findAll");
for (User user : userList) {
System.out.println(user);
}
}
}
运行结果
三、MyBatis的CRUD回顾
1.新增
- 在UserMapper.xml中编写新增语句
<insert id="saveUser" parameterType="com.lagou.pojo.User">
insert into user values (#{id},#{username})
</insert>
- 编写测试类
@Test
public void testInsert() throws IOException {
InputStream stream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(stream);
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = new User();
user.setId(3);
user.setUsername("lilei");
sqlSession.insert("user.saveUser",user);
//增删改都要提交事务才生效
sqlSession.commit();
sqlSession.close();
}
- 运行结果
2.修改
- 在UserMapper.xml中编写修改语句
<update id="updateUser" parameterType="com.lagou.pojo.User">
update user set username=#{username} where id = #{id}
</update>
- 编写测试类
@Test
public void testUpdate() throws IOException {
InputStream stream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(stream);
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = new User();
user.setId(1);
user.setUsername("wangwu");
sqlSession.update("user.updateUser",user);
//增删改都要提交事务才生效
sqlSession.commit();
sqlSession.close();
}
- 运行结果
3.删除
- 在UserMapper.xml中编写修改语句
<!-- 当参数为基本数据类型或其包装类时或String类型,并且仅有一个参数,sql中占位参数名字可以随便写-->
<delete id="deleteUser" parameterType="java.lang.Integer">
delete from user where id=#{abc}
</delete>
- 编写测试类
@Test
public void testDelete() throws IOException {
InputStream stream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(stream);
SqlSession sqlSession = sqlSessionFactory.openSession();
sqlSession.delete("user.deleteUser",1);
//增删改都要提交事务才生效
sqlSession.commit();
sqlSession.close();
}
- 运行结果
四、MyBatis相关配置文件回顾
1.MyBatis映射配置文件xxxMapper.xml
2.入门核心配置文件sqlMapConfig.xml
2.1层级关系
2.2常用配置解析
- environments :数据库环境配置,可以配置多个环境
- transactionManager : 事务管理器 类型有两种。
①JDBC:使用JDBC的提交和回滚设置,它依赖于从数据源得到连接来管理事务
②MANAGED:他不提交或回滚操作,而是交由容器来管理声明周期。默认一次操作结束后它会关闭连接,可以通过设置closeConnection=false来关闭默认关闭行为。 - dataSource :数据源 类型有三种
①POOLED :使用连接池进行管理连击
②UNPOOLED : 每次都打开一个新的连接,使用完毕后断开连接
③JNDI : 供jboos等服务器使用,将数据库的连接信息保存在项目以外的地方
- mappers :加载映射配置文件,共有四种方式
<!-- 相对类路径的资源引用-->
<mapper resource="UserMapper.xml"/>
<!-- 文件绝对路径的引用-->
<mapper url="/opt/resource/xxx.xml"/>
<!-- 使⽤映射器接⼝实现类的完全限定类名 -->
<mapper class="com.lagou.mapper.UserMapper"/>
<!-- 将包内的所有映射接口全部加载,要求xml和接口在同一个目录下,且接口名和xml文件名一致 -->
<package name="com.lagou.mapper"/>
五、MyBatis相关API回顾
1.SqlSessionFactoryBuilder
sqlSession工厂构造器。
//通过以流的方式加载配置文件并返回一个sqlSessionFactory对象
SqlSessionFactory build(InputStream inputStream)
2.SqlSessionFactory
sqlSession工厂,它有多个方法创建sqlSession,常用的有两个
//建立一个sqlSession,默认会开启事务,但是不会自动提交事务,需要手动进行提交
SqlSession openSession();
//参数为true时,会自动提交事务,无需手动处理
SqlSession openSession(boolean autoCommit);
3.SqlSession
sql会话,包含了增删改查、事务操作等
//数据操作
<T> T selectOne(String statement,Object parameter);
<E> List<E> selectList(String statement,Object parameter);
int insert(String statement,Object parameter);
int delete(String statement,Object parameter);
int update(String statement,Object parameter);
//事务操作
void commit();
void rollback();
六、MyBatis的Dao层传统开发方式回顾
- 创建dao接口
package com.lagou.dao;
import com.lagou.pojo.User;
import java.io.IOException;
import java.util.List;
public interface IUserDao {
/**
* 查询所有用户
*/
List<User> findAll() throws IOException;
}
- 创建dao接口的实现
package com.lagou.dao;
import com.lagou.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class UserDaoImpl implements IUserDao{
@Override
public List<User> findAll() throws IOException {
InputStream stream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(stream);
SqlSession sqlSession = sqlSessionFactory.openSession();
List<User> userList = sqlSession.selectList("user.findAll");
sqlSession.close();
return userList;
}
}
- 编写测试类
@Test
public void testDao() throws IOException{
IUserDao userDao = new UserDaoImpl();
List<User> userList = userDao.findAll();
for (User user : userList) {
System.out.println(user);
}
}
七、MyBatis的Dao层代理开发方式回顾
1.介绍
- 实际开发中代理开发是主流的方式
- 采用代理模式时,程序员只需要编写Mapper接口,无需关系Mapper实现,由MyBatis通过接口定义创建接口的动态代理类,具体实现与传统开发方式中的Dao实现类似
2.规范
- Mapper.xml⽂件中的namespace与mapper接⼝的全限定名相同
- Mapper接⼝⽅法名和Mapper.xml中定义的每个statement的id相同
- Mapper接⼝⽅法的⼊参类型和mapper.xml中定义的每个sql的parameterType的类型相同
- Mapper接口方法的出参类型和mapper.xml中定义的每个sql的resultType的类型相同,当返回集合对象时,resultType设置的是具体泛型类型
3.代码实现
- 新建UserMapper2.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="com.lagou.dao.IUserDao">
<select id="findAll" resultType="com.lagou.pojo.User">
select * from user
</select>
</mapper>
- 修改核心配置文件,添加UserMapper2.xml的配置
<mappers>
<mapper resource="UserMapper.xml"/>
<mapper resource="UserMapper2.xml"/>
</mappers>
- 创建dao接口
与传统方式的IUserDao一样,不在新建,直接复用 - 编写测试方法
@Test
public void testProxy() throws IOException{
InputStream stream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(stream);
SqlSession sqlSession = sqlSessionFactory.openSession();
IUserDao userDao = sqlSession.getMapper(IUserDao.class);
List<User> userList = userDao.findAll();
for (User user : userList) {
System.out.println(user);
}
sqlSession.close();
}
八、MyBatis的properties深入
- 在项目开发中,数据库的配置信息会单独存放在配置文件中,使用properties标签可以引入配置文件
- properties标签要求在配置文件的最前端,如果顺序不对会提示错误信息
- 通过${属性名}来引用配置内容
九、MyBatis的typeAliases深入
- 为java类型设置短名字
- MyBatis已经内置对基本类型的别名,如 string、int、double
- 别名大小写不敏感
<typeAliases>
<!-- 单独对某个类设置别名 -->
<typeAlias type="com.lagou.pojo.User" alias="user"/>
<!-- 对包下的类都设置别名,别名为类名 -->
<package name="com.lagou.pojo"/>
</typeAliases>
十、MyBatis的动态SQL-if标签回顾
- 适用于根据某些满足的条件进行查询
- if标签内test中间为测试条件,满足时拼接标签内的sql,不满足直接跳过
- where标签会自动处理第一个and
<select id="findByCondition" parameterType="user" resultType="user">
select * from user
<where>
<if test="id !=null">
and id = #{id}
</if>
<if test="username != null">
and username = #{username}
</if>
</where>
</select>
十一、MyBatis的动态SQL-foreach标签回顾
- 适用于多值查询,如 id in (1,2,4)
- collection : 要遍历的集合元素,数组时用array,集合时用collection或list,Map时用需要遍历的value的key
- open :语句的开始部分
- close :语句的结束部分
- item : 每个遍历的元素的名字,foreach标签内引用的变量#{}需一致
- separator : 分隔符
<!-- 实际拼接起来的sql = sql + open + item + separator + close -->
<select id="findByIds" resultType="user">
select * from user
<where>
<foreach collection="array" open="id in (" close=")" item="ids" separator=",">
#{ids}
</foreach>
</where>
</select>
对于sql中相同片段,可以单独抽离出来成sql片段并设置唯一id,用include标签进行复用,通过refid指明要引用的sql片段
<sql id="selectAllUser">
select * from user
</sql>
<select id="findByIds" resultType="user">
<include refid="selectAllUser"/>
<where>
<foreach collection="array" open="id in (" close=")" item="ids" separator=",">
#{ids}
</foreach>
</where>
</select>