1、Mybatis 介绍
Mybatis 是一个支持普通 SQL 查询,存储过程和高级映射的优秀持久层框架,用于简化 jdbc 代码,简化持久层,将 SQL 语句从代码中分离,利用反射,将表中的数据与 Javabean 属性一一映射。
2、Mybatis 使用
2.1、基本步骤:
-
下载依赖 jar 包和数据库资源包,加载到项目中
-
配置 Mybatis 核心配置文件 mybatis-config.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">
<!--配置-->
<configuration>
<!--
default 选择现在要使用的环境配置
与对应 environment 的 id 属性值相同
-->
<environments default="dev">
<!--环境的配置-->
<environment id="dev">
<!--事务管理 : 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 映射文件-->
<mappers>
<mapper resource="com/yml/mappers/DeptMapper.xml"/>
</mappers>
</configuration>
-
提供使用的实体类
public class Dept {
private int deptno;
private String dname;
private String loc;
public Dept() {
}
public Dept(int deptno, String dname, String loc) {
this.deptno = deptno;
this.dname = dname;
this.loc = loc;
}
public int getDeptno() {
return deptno;
}
public void setDeptno(int deptno) {
this.deptno = deptno;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
@Override
public String toString() {
return "Dept{" +
"deptno=" + deptno +
", dname='" + dname + '\'' +
", loc='" + loc + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Dept dept = (Dept) o;
return deptno == dept.deptno &&
Objects.equals(dname, dept.dname) &&
Objects.equals(loc, dept.loc);
}
@Override
public int hashCode() {
return Objects.hash(deptno, dname, loc);
}
}
-
提供 SQL 映射文件 DeptMapper.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">
<!--
SQL映射文件 : 主要定义sql语句
namespace : 命名空间
通过命名空间区分sql映射文件的唯一,唯一标识
唯一的,不可重的
可以任意定义组成
建议 : sql映射文件的包名的.文件名
-->
<mapper namespace="com.yml.mappers.DeptMapper">
<!--
select 标签定义select语句->处理块
id : sql语句的唯一,在同一个命名空间下不能重复
parameterType : 参数类型|入参类型
基本数据类型|包装类 String Date Javabean 数组 List Map
resultType : 结果类型
基本数据类型|包装类 String Date Javabean List Map
如果结果是一个List集合,resultType定义泛型类型
-->
<select id="selectAll" resultType="com.yml.pojo.Dept">
select * from dept
</select>
</mapper>
-
测试使用
public class Test01 {
public static void main(String[] args) throws IOException {
// 1、加载核心配置文件
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
// 2、获取 SqlSessionFactory 实例
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
// 3、获取会话
SqlSession session = factory.openSession();
// 4、使用
// selectList("命名空间.id")
List<Dept> list = session.selectList("com.yml.mappers.DeptMapper.selectAll");
list.forEach(System.out::println);
// 5、关闭会话
session.close();
}
}
2.2、优化:
-
提取数据库连接配置 db.properties
driver = oracle.jdbc.driver.OracleDriver
url = jdbc:oracle:thin:@localhost:1521:XE
username = SCOTT
password = TIGER
<!-- 加载外部的 properties 文件 -->
<properties resource="db.properties" />
<!--数据源信息的配置 type="POOLED" 选择连接池技术 -->
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
-
设置别名
mybatis-config.xml:
<!--配置别名-->
<typeAliases>
<!-- 包下所有的类默认类名,不区分大小写 -->
<package name="com.yml.pojo"/>
</typeAliases>
DeptMapper.xml:
<select id="selectAll" resultType="Dept">
select * from dept
</select>
-
封装工具类
public class SessionUtils {
private static SqlSessionFactory factory = null;
static {
try {
factory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 获取会话
* @return
*/
public static SqlSession getSession(){
SqlSession session = null;
if (factory != null){
// 设置事务自动提交
session = factory.openSession(true);
}
return session;
}
}
2.3、查询
2.3.1 查询方法
-
// selectList(String s); List<Dept> list = session.selectList("com.yml.mappers.DeptMapper.selectAll");
-
// selectOne(String var1, Object var2); Dept dept = session.selectOne("com.yml.mappers.DeptMapper.selectDeptByDeptno", 30);
-
// <K, V> Map<K, V> selectMap(String var1, String var2); // <K, V> Map<K, V> selectMap(命名空间.id, sql 语句的实参, 作为 key 的字段名); // 注意: 作为 key 的字段应为是一个唯一性较高的字段 Map<Integer, String> map = session.selectMap("com.yml.mappers.DeptMapper.selectDepeByDname", "SALES", "dname");
2.3.2、入参类型
-
基本数据类型 | 包装类
-
String
<!--String : 根据用户名模糊查询 -->
<select id="selectEmpByLikeEname" parameterType="String" resultType="Emp">
select * from emp where ename like '%'||#{ename}||'%'
</select>
// String : 根据用户名模糊查询
List<Emp> list = session.selectList("com.yml.mappers.EmpMapper1.selectEmpByLikeEname", "A");
-
Date
<!--Date : 查询某一个日期入职的员工-->
<select id="selectEmpByDate" parameterType="date" resultType="Emp">
select * from emp where hiredate = #{hiredate}
</select>
// Date : 查询某一个日期入职的员工 1981/12/3
Date date = new SimpleDateFormat("yyyy/MM/dd").parse("1981/12/3");
list = session.selectList("com.yml.mappers.EmpMapper1.selectEmpByDate", date);
-
Javabean
<!-- Javabean: 根据员工姓名与员工薪资查询员工信息 -->
<select id="selectEmpByEnameAndSal" parameterType="Emp" resultType="Emp">
select * from emp where ename = #{ename} and sal = #{sal}
</select>
// Javabean: 根据员工姓名与员工薪资查询员工信息
Emp emp = new Emp();
emp.setEname("KING");
emp.setSal(5000);
list = session.selectList("com.yml.mappers.EmpMapper1.selectEmpByEnameAndSal", emp);
-
数组 | List
<!--数组|List: 根据部门编号查询部门信息 -->
<select id="selectEmpByDeptno" resultType="Emp">
select * from emp where deptno in (
/*遍历 : 集合|数组 collection = "array|list" item="item" 作为每次循环的数据值 separator: 设置分隔符 */
<foreach collection="array" item="item" separator=",">
#{item}
</foreach>
)
</select>
// 数组|List: 根据部门编号查询部门信息
list = session.selectList("com.yml.mappers.EmpMapper1.selectEmpByDeptno", new int[]{20, 30});
-
Map
<!-- Map: 根据工种或者部门编号查询员工信息-->
<select id="selectEmpByJobOrDeptno" parameterType="map" resultType="Emp">
select * from emp where job = #{job} or deptno = #{deptno}
</select>
// Map: 根据工种或者部门编号查询员工信息
list = session.selectList("com.yml.mappers.EmpMapper1.selectEmpByJobOrDeptno", Map.of("job", "MANAGER", "deptno", "10"));
2.3.3、增删改
<mapper namespace="com.yml.mappers.EmpMapper2">
<insert id="insertEmp" parameterType="Emp">
insert into emp(empno, ename, sal, deptno) values (#{empno}, #{ename}, #{sal}, #{deptno})
</insert>
<update id="updateEmp" parameterType="Emp">
update emp set ename = #{ename} where empno = #{empno}
</update>
<delete id="deleteEmp" parameterType="int">
delete from emp where deptno = #{deptno}
</delete>
</mapper>
public class Test03 {
public static void main(String[] args) {
SqlSession session = SessionUtils.getSession();
Emp emp = new Emp();
emp.setEmpno(8888);
emp.setEname("yzq");
emp.setSal(88.88);
emp.setDeptno(40);
// insert
// int rows = session.insert("com.yml.mappers.EmpMapper2.insertEmp", emp);
// update
// emp.setEname("zzy");
// int rows = session.delete("com.yml.mappers.EmpMapper2.updateEmp", emp);
// delete
int rows = session.delete("com.yml.mappers.EmpMapper2.deleteEmp", 40);
if (rows > 0){
System.out.println("成功!!!");
}
else {
System.out.println("失败!!!");
}
session.close();
}
}
2.3.4、返回类型
-
基本数据类型 | 包装类
<!--基本数据类型-->
<select id="selectSalByEmpno" parameterType="int" resultType="double">
select sal from emp where empno = #{empno}
</select>
double sal = session.selectOne("com.yml.mappers.EmpMapper3.selectSalByEmpno", 7499);
-
String
<!--String : 根据部门编号查询员工姓名-->
<select id="selectEnameByDeptno" parameterType="int" resultType="String">
select ename from emp where deptno = #{deptno}
</select>
List<String> list = session.selectList("com.yml.mappers.EmpMapper3.selectEnameByDeptno", 30);
-
Date
<!--Date 根据员工编号,查询员工入职日期-->
<select id="selectDateByEmpno" parameterType="int" resultType="Date">
select hiredate from emp where empno = #{empno}
</select>
Date date = session.selectOne("com.yml.mappers.EmpMapper3.selectDateByEmpno", 7654);
-
Javabean
<select id="selectEmpByDeptno" parameterType="int" resultType="Emp">
select * from emp where deptno = #{deptno}
</select>
-
Map
<select id="selectEmpByEmpno" parameterType="int" resultType="map">
select * from emp where empno = #{empno}
</select>
Map map = session.selectOne("com.yml.mappers.EmpMapper3.selectEmpByEmpno", 7900);
-
List<Map>
<select id="selectEmpByJob" parameterType="String" resultType="map">
select * from emp where job = #{job}
</select>
List<Map<String, Object>> ls = session.selectList("com.yml.mappers.EmpMapper3.selectEmpByJob", "MANAGER");
3、接口绑定方案
3.1、使用步骤:
-
定义接口
-
接口文件要与对应的 Mapper 映射文件放在同一路径下
-
保证文件同名
-
public interface EmpMapper {
}
-
提供接口映射文件
-
Mapper 文件的命名空间定义为与之绑定的接口的权限定名(包名.类名)
-
SQL 语句的 id 与对应的接口中的方法中的方法名相同
-
SQL 的参数和返回值要求与抽象方法的参数和返回值保持一致
-
-
扫描接口文件
<mappers>
<!--扫描一个接口文件-->
<!--<mapper class="com.yml.mappers.EmpMapper"></mapper>-->
<!--扫描一个包下的所有接口文件-->
<package name="com.yml.mappers"/>
</mappers>
测试代码:
public interface EmpMapper {
public List<Emp> selectALL();
/*根据员工编号查询员工信息*/
Emp selectEmpByEmpno(int empno);
/*根据员工姓名与员工薪资查询员工信息*/
List selectEmpByEnameAndSal(@Param("ename") String ename, @Param("sal") double sal);
}
<mapper namespace="com.yml.mappers.EmpMapper">
<select id="selectALL" resultType="Emp">
select * from emp
</select>
<select id="selectEmpByEmpno" parameterType="int" resultType="Emp">
select * from emp where empno = #{empno}
</select>
<!--当多参数时候 : 占位符的名字可以默认为: parameters are [arg1, arg0, param1, param2]*/
/*select * from emp where ename=#{arg0} and sal = #{arg1}-->
<select id="selectEmpByEnameAndSal" resultType="Emp">
select * from emp where ename = #{ename} and sal = #{sal}
</select>
</mapper>
public class Test01 {
public static void main(String[] args) {
// 1.获取会话
SqlSession session = SessionUtils.getSession();
// 2.获取接口的实现类对象
EmpMapper mapper = session.getMapper(EmpMapper.class);
List<Emp> list = mapper.selectALL();
list.forEach(System.out::println);
System.out.println("----------------------------------------------------");
Emp emp = mapper.selectEmpByEmpno(7369);
System.out.println(emp);
System.out.println("----------------------------------------------------");
list = mapper.selectEmpByEnameAndSal("KING", 5000.00);
list.forEach(System.out::println);
// 关闭会话
session.close();
}
}
3.2、增删改
public interface EmpMapper2 {
int insertEmp(Emp emp);
int updateEmp(@Param("ename") String ename, @Param("empno") int empno);
int deleteEmp(int empno);
}
<mapper namespace="com.yml.mappers.EmpMapper2">
<insert id="insertEmp" parameterType="Emp">
insert into emp(empno, ename, sal, deptno) values(#{empno}, #{ename}, #{sal}, #{deptno})
</insert>
<update id="updateEmp">
update emp set ename = #{ename} where empno = #{empno}
</update>
<delete id="deleteEmp" parameterType="int">
delete from emp where empno = #{empno}
</delete>
</mapper>
public class Test02 {
public static void main(String[] args) {
SqlSession session = SessionUtils.getSession();
EmpMapper2 mapper2 = session.getMapper(EmpMapper2.class);
Emp emp = new Emp();
emp.setEmpno(1234);
emp.setEname("杨志强");
emp.setSal(3.21);
emp.setDeptno(40);
// mapper2.insertEmp(emp);
// mapper2.updateEmp("朱正洋", 1234);
mapper2.deleteEmp(1234);
session.close();
}
}
3.3、批量增删改
public interface EmpMapper3 {
int insertEmp(List<Emp> list);
int updateEmp(List<Emp> list);
int deleteEmp(List<Integer> list);
}
<mapper namespace="com.yml.mappers.EmpMapper3">
<insert id="insertEmp">
insert into emp(empno, ename, sal, deptno)
<foreach collection="list" item="item" separator="union">
select #{item.empno}, #{item.ename}, #{item.sal}, #{item.deptno} from dual
</foreach>
</insert>
<update id="updateEmp">
<foreach collection="list" item="item" separator=";" open="begin" close=";end;">
update emp set ename = #{item.ename} where empno = #{item.empno}
</foreach>
</update>
<delete id="deleteEmp">
delete from emp where empno in (
<foreach collection="list" item="item" separator=",">
#{item}
</foreach>
)
</delete>
</mapper>
public class Test03 {
public static void main(String[] args) {
SqlSession session = SessionUtils.getSession();
EmpMapper3 mapper3 = session.getMapper(EmpMapper3.class);
// List list = List.of(
// new Emp(1111, "杨志强", 3.21, 40),
// new Emp(2222, "朱正洋", 4.32, 30)
// );
// mapper3.insertEmp(list);
List list = List.of(
new Emp(1111, "yzq", 3.21, 40),
new Emp(2222, "zzy", 4.32, 30)
);
mapper3.updateEmp(list);
mapper3.deleteEmp(List.of(1111, 2222));
session.close();
}
}