MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架。MyBatis消除了几乎所有的 JDBC代码和参数的手工设置以及对结果集的检索封装。MyBatis可以使用简单的XML或注解用于配置和 原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。
1.MyBatis使用步骤
- 1.下载jar包
- 2.jar包资源拿到项目中,add as lib... mybatis核心jar包 mybatis依赖jar包 数据库的驱动jar包
- 3.定义mybatis核心配置文件--> 参考文档+官网
- 4.定义sql映射文件 定义要执行的sql语句
- 5.jar类中进行测试 加载核心配置文件 构建工厂 获取回话 执行sql 处理结果 关闭回话
三个常用查询方法:
- selectOne() 执行指定sql,得到一个结果
- selectList() 执行指定sql,得到一个list集合,如果没查到,返回List中没有数据,但是不是null
- selectMap() 执行指定sql,得到一个Map集合,如果没查到,返回空map
核心配置文件:
<?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">
<!--根元素: 核心配置-->
<configuration>
<!--
环境配置
default : 要使用的环境的id值
-->
<environments default="ev">
<!--environment : 一个环境的配置 id: 当前环境的唯一标识 -->
<environment id="ev">
<!--transactionManager 事务管理器 type="JDBC" :选择与jdbc相同的事务管理机制 -->
<transactionManager type="JDBC"/>
<!--数据源配置 type="POOLED" : 通过数据库连接池管理连接-->
<dataSource type="POOLED">
<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映射配置加载 : 定义sql语句的配置文件-->
<mappers>
<mapper resource="com/yjxxt/mappers/DeptMapper.xml"/>
</mappers>
</configuration>
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 命名空间 -> 是sql映射文件的唯一标识
1) 不能重复,随便写->不推荐
2) 建议设置为当前的表名.文件名(不加后缀)
-->
<mapper namespace="com.yjxxt.mappers.DeptMapper">
<!--
select 定义查询语句
标签对中定义查询语句
id : sql语句的唯一标识
resultType : 结果类型 : 基本数据类型|包装类 String Date Javabean List Map
parameterType : 入参类型 : 基本数据类型|包装类 String Date Javabean 数组 List Map
-->
<select id="queryAll" resultType="com.yjxxt.entity.Dept" >
select * from dept
</select>
<!--根据部门编号查询部门对象-->
<select id="queryDeptByNo" parameterType="int" resultType="com.yjxxt.entity.Dept">
select * from dept where deptno = #{deptno}
</select>
</mapper>
运行测试程序:
//实例代码-基本Mybatis使用流程
public class Class001_Dept {
public static void main(String[] args) throws IOException {
//1.加载mybatis的核心配置文件
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
//2.构建SqlSessionFactory
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
//3.根据工厂构建回话
SqlSession session = factory.openSession();
//4.执行sql,得到结果
//selectList("命名空间.id")
//selectList("命名空间.id",sql语句的实参)
List<Dept> list = session.selectList("com.yjxxt.mappers.DeptMapper.queryAll");
//session.selectOne("命名空间.id");
//session.selectOne("命名空间.id",sql语句的实参);
Dept dept = session.selectOne("com.yjxxt.mappers.DeptMapper.queryDeptByNo",20);
//session.selectMap("命名空间.id","作为key的字段名")
//session.selectMap("命名空间.id",sql语句的实参,"作为key的字段名")
Map<String,Dept> map = session.selectMap("com.yjxxt.mappers.DeptMapper.queryAll","dname");
//5.处理结果
list.forEach(System.out::println);
System.out.println(dept);
System.out.println(map);
//6.关闭回话
session.close();
}
}
2.properties标签和typeAliases标签
(1)properties标签
通过properties标签实现软编码,src下定义配置文件db.properties,mybatis核心配置文件中添加properties标签,指定加载外部的properties文件,注意定义位置。
注:获取properties文件中数据时候,要通过${}的方式获取
(2)typeAliases标签
作用:用于给java类型定义别名,方便在配置文件中使用(以下三种)
- 给User类定义别名为u
- 省略alias属性, 表示类别名为类名, 大小写不敏感
- 可以通过package标签给整个包下的所有类定义别名,别名为类名
//实例代码-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">
<!--根元素: 核心配置-->
<configuration>
<!-- 加载外部的properties文件 -->
<properties resource="db.properties" />
<!--配置别名,别名不区分大小写-->
<typeAliases>
<package name="com.xjm.entity"/>
</typeAliases>
<!--环境配置-->
<environments default="ev">
<environment id="ev">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<!--sql映射配置加载-->
<mappers>
<package name="com.xjm.mappers"/>
</mappers>
</configuration>
3.parameterType入参类型
如果执行的是条件查询,DML,需要在调用方法的时候传递参数,此时, 可以在sql标签中通过 parameterType属性指定参数的类型(别名|权限定名). 而在sql语句,通过#{}的方式获取参数。
parameterType: 基本数据类型(四类八种) 包装类 String Date Javabean Map List 数组
(1)一个参数的查询
SQL映射文件的配置:
//根据员工姓名查询员工数据,返回类型为emp
<?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.yjxxt.mappers.EmpMapper">
<!--
入参类型: 基本数据类型 包装类 String Date Javabean 数组 List Map
-->
<!--String : 根据员工想命名查询员工数据-->
<select id="queryEmpByName" resultType="Emp" parameterType="string">
select * from emp where ename = #{haha}
</select>
</mapper>
运行程序文件:
//实例代码-一个参数类型的查询
public class Class001_EmpTest {
public static void main(String[] args) {
//1.获取回话
SqlSession session = null;
try {
session = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml")).openSession();
//2.执行sql
//String 根据员工想命名查询员工数据
List<Emp> list = session.selectList("com.yjxxt.mappers.EmpMapper.queryEmpByName","SMITH");
list.forEach(System.out::println);
list3.forEach(System.out::println);
} catch (IOException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} finally {
//3.关闭回话
if(session!=null){
session.close();
}
}
}
}
(2)多个参数查询
多个参数传递时, 由于sqlSession中提供的查询方法,只允许传递一个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">
<!--命名空间-->
<mapper namespace="com.yjxxt.mappers.EmpMapper">
<!--
入参类型: 基本数据类型 包装类 String Date Javabean 数组 List Map
-->
<!--JAVABEAN : 根据员工姓名,员工部门编号同时查询员工信息-->
<select id="queryEmpByNameDeptno" parameterType="emp" resultType="emp">
select * from emp where ename=#{ename} and deptno = #{deptno} /*如果参数为javabean对象,占位符的名字需要与对应属性名保持一致*/
</select>
<!--数组|list : 根据员工编号查询多个员工数据-->
<select id="queryEmpByEmpnoSome" resultType="emp">
select * from emp where empno in
<foreach collection="array" item="item" open="(" close=")" separator=",">
#{item}
</foreach>
</select>
<!--Map : 查询薪资>1500或者部门在30部门的员工信息-->
<select id="queryEmpBySalDeptno" resultType="emp" parameterType="map">
select * from emp where sal> #{sal} or deptno = #{deptno} /*如果入参为map,占位符的名字要对象键值对的key,根据key获取value*/
</select>
</mapper>
运行程序文件:
//实例代码-多个参数查询
public class Class001_EmpTest {
public static void main(String[] args) {
//1.获取回话
SqlSession session = null;
try {
session = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml")).openSession();
//2.执行sql
//JAVABEAN : 根据员工姓名,员工部门编号同时查询员工信息
Emp emp = new Emp();
emp.setEname("SMITH");
emp.setDeptno(20);
Emp e = session.selectOne("com.yjxxt.mappers.EmpMapper.queryEmpByNameDeptno",emp);
System.out.println(e);
System.out.println("--------------------------------");
//数组|list : 根据员工编号查询多个员工数据
Map<Integer,Emp> map = session.selectMap("com.yjxxt.mappers.EmpMapper.queryEmpByEmpnoSome",new int[]{7369,7902},"empno");
System.out.println(map);
System.out.println("--------------------------------");
//Map : 查询薪资>1500或者部门在30部门的员工信息
List<Emp> list3 = session.selectList("com.yjxxt.mappers.EmpMapper.queryEmpBySalDeptno",Map.of("sal",1500,"deptno",30));
list3.forEach(System.out::println);
} catch (IOException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} finally {
//3.关闭回话
if(session!=null){
session.close();
}
}
}
}
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">
<!--命名空间-->
<mapper namespace="com.yjxxt.mappers.EmpMapper2">
<!--增删改默认结果类型为影响行数-->
<insert id="addEmp" parameterType="emp">
insert into emp(empno,ename,sal,deptno) values(#{empno},#{ename},#{sal},#{deptno})
</insert>
<update id="updateEnameByEmpno" parameterType="Emp">
update emp set ename = #{ename} where empno = #{empno}
</update>
<delete id="deleteEmpSome">
delete from emp where empno in(
<foreach collection="list" item="item" separator=",">
#{item}
</foreach>
)
</delete>
</mapper>
运行程序文件:
public class Class002_EmpTest {
public static void main(String[] args) {
//1.获取回话
SqlSession session = null;
try {
session = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml")).openSession(); /*openSession(true) 自动提交事务,默认手动提交*/
//2.执行sql
//insert
Emp emp = new Emp();
emp.setEmpno(9999);
emp.setEname("胡歌");
emp.setSal(2000);
emp.setDeptno(40);
/*int rows = session.insert("com.yjxxt.mappers.EmpMapper2.addEmp",emp);
if(rows>0){
session.commit(); //事务提交
}else{
session.rollback(); //事务回滚
}
System.out.println(rows>0?"跟新成功":"更新失败");*/
//update
/*emp.setEname("彭于晏");
int rows = session.update("com.yjxxt.mappers.EmpMapper2.updateEnameByEmpno",emp);
if(rows>0){
session.commit();
System.out.println("更新成功");
}else{
session.rollback();
System.out.println("更新失败");
}*/
//delete
int rows = session.delete("com.yjxxt.mappers.EmpMapper2.deleteEmpSome",List.of(9999,7999));
if(rows>0){
session.commit();
System.out.println("更新成功");
}else{
session.rollback();
System.out.println("更新失败");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//3.关闭回话
if(session!=null){
session.close();
}
}
}
}
5. 接口绑定方案
Myabaits会自动将接口与xml文件进行绑定,实际上就是Mybatis互根据接口和对应的xml文件创建一个接 口的实现类,换言之,就是可以得到接口类型的一个对象,方便方法的调用。
(1)定义接口
public interface EmpMapper {
//查询所有的员工数据
public List<Emp> queryAllEmp();
}
(2)SQL映射文件配置
注(测试接口绑定方案下的sql映射文件):
- 1.接口与sql映射文件在同一个包中
- 2.接口与sql映射文件同名
- 3.sql映射文件的命名空间namespace,要求定义为接口的包名.接口名(权限定名)
- 4.sql标签的id属性值定义为与其对应的接口中抽象方法名
- 5.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映射文件的命名空间namespace,要求定义为接口的包名.接口名(权限定名)-->
<mapper namespace="com.yjxxt.mappers.EmpMapper">
<!--查询所有的员工数据 || sql标签的id属性值定义为与其对应的接口中抽象方法名-->
<!--sql的返回值与参数要求与抽象方法的返回值与参数保持一致-->
<select id="queryAllEmp" resultType="emp">
select * from emp
</select>
</mapper>
(3)运行程序文件
在使用时,通过SqlSession的getMapper() 方法,返回接口代理对象,从而调用以实现的抽象方法
//sqlSession回话的封装工具类-SSessionUtils
//工具类中封装了加载配置文件和获取回话的方法
public class Class001_interface_bind {
public static void main(String[] args) {
//1.获取回话
SqlSession session = SessionUtils.getSession();
//2.获取接口的实现类对象
//接口多态
EmpMapper mapper = session.getMapper(EmpMapper.class);
//3.调用功能
List<Emp> list = mapper.queryAllEmp();
list.forEach(System.out::println);
//4.关闭回话
session.close();
}
}
6.接口绑定实现基本CRUD操作
1.定义接口文件
//实例代码-接口文件定义增删改除的方法
public interface EmpMapper {
//查询所有的员工数据
public List<Emp> queryAllEmp();
//根据员工编号查询员工信息
public Emp queryEmpByNo(int empno);
//根据员工薪资与部门查询满足条件的员工姓名
public List<String> queryNameBySalDeptno(@Param("sal") double sal, @Param("deptno") int deptno);
//删除
public int deleteEmpByEmpno(int empno);
//插入
public int addEmp(Emp emp);
}
2.SQL映射文件配置
//实例代码-SQL映射文件增删改除语句
<mapper namespace="com.yjxxt.mappers.EmpMapper">
<!--查询所有的员工数据-->
<select id="queryAllEmp" resultType="emp">
select * from emp
</select>
<select id="queryEmpByNo" parameterType="int" resultType="emp">
select * from emp where empno = #{empno}
</select>
<select id="queryNameBySalDeptno" resultType="string">
select ename from emp where sal>#{sal} and deptno = #{deptno} /*[arg1, arg0, param1, param2] 匹配参数抽象方法的列表*/
</select>
<delete id="deleteEmpByEmpno" parameterType="int">
delete from emp where empno = #{empno}
</delete>
<insert id="addEmp" parameterType="emp">
insert into emp(empno,ename,deptno) values(#{empno},#{ename},#{deptno})
</insert>
</mapper>