JavaWEB大神成长篇:MyBatis传统DAO模式开发实战精解(第六期)
·
4_MyBatis传统DAO模式开发
-
概念
-
1_sqlSession查询的三种方式
-
SqlSession对象本身的API中就有三个查询方法, 分别能够实现如下查询方式
-
接下来我们就对这三个方法进行一个快速的学习

-
创建 Emp 实体类
@AllArgsConstructor @NoArgsConstructor @Data public class Emp implements Serializable { private Integer empno; private String ename; private String job; private Integer mgr; private Date hiredate; private Double sal; private Double comm; private Integer deptno; } -
准备 Mapper 映射文件
<?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="EmpMapper"> <!-- 返回单个对象 public Emp findOne(); id 相当于方法名 resultType 相当于返回值类型 sql语句的查询结果用哪个类来进行封装 如果返回值类型是集合,这里写的也是集合中的元素对应的类,不是集合本身作为类型 paramaterType 参数类型 SQL语句就是具体的方法体的实现 --> <select id="findOne" resultType="emp" > select * from emp where empno = 7499 </select> <!-- 返回多个对象List集合 查询全部的员工信息 public List<Emp> findAll() --> <select id="findAll" resultType="emp"> select * from emp </select> <!--返回多个对象的Map集合 把查询出来的数据中的某一列作为键, 整条数据封装的对象作为值 public Map<key,Emp> findEmpMap() <empno,Emp> <key,Emp> --> <select id="findEmpMap" resultType="map"> select * from emp </select> </mapper>
-
-
2_sqlSession传递参数的三种方式
-
1.单个基础数据类型作为参数
-
2.多个基础数据类型的 map 集合作为参数
-
3.引用类型作为参数
-
Mapper 映射文件
<?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="EmpMapper2"> <!-- 参数为一个基本数据类型 根据员工工号查询员工的全部信息, 返回单个员工对象 public Emp findByEmpno(int empno); parameterType 在有参数情况下也是可以省略不写 mybatis 可以根据实际情况自动判断 如果要写 parameterType 那么就要写对 在SQL语句上可以使用 ${} #{} 代表参数的占位 如果参数是单个基本数据类型, {}中名字可以随便写, 见名知意${} 代表mybatis底层使用Statment语句对象,参数是以字符串拼接的形式设置 ${} 代表mybatis底层使用Statment语句对象,参数是以字符串拼接的形式设置 #{} 代表mybatis底层使用的preparedStatment语句对象,参数使用?作为占位符处理 #{} 以后常用 --> <select id="findByEmpno" resultType="emp" parameterType="int"> select * from emp where empno = #{empno} </select> <!-- 参数为 map 集合 查询指定部门号和指定最低薪资的员工信息 20 号部门 且工资在 1500 以上的员工信息 public List<Emp> findEmpByDeptnoAndSal(int deptno, double sal); < > 最好要进行转译处理, 参照 HTML 转译 w3school 在线文档中有转译符号对应规则 Map<String,Object> args=new HashMap<>(); args.put("deptno", 20); args.put("sal", 1500.0); #{} 中写的是 map 集合中, 参数的键 --> <select id="findEmpByDeptnoAndSal" resultType="emp" parameterType="map"> select * from emp where deptno = #{deptno} and sal >= #{sal} </select> <!-- 参数为对象 emp >>> deptno sal 参数是我们自定义的类型, 那么 #{} 中写的是参数的属性名 --> <select id="findEmpByDeptnoAndSal2" resultType="emp" parameterType="emp"> select * from emp where deptno = #{deptno} and sal >= #{sal} </select> </mapper> -
测试代码
package com.xxx.test; import com.xxx.pojo.Emp; 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.After; import org.junit.Before; import org.junit.Test; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; public class Test3 { private SqlSession sqlSession; @Before public void init(){ SqlSessionFactoryBuilder ssfb = new SqlSessionFactoryBuilder(); InputStream resourceAsStream = null; try { resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml"); } catch (IOException e) { e.printStackTrace(); } SqlSessionFactory factory = ssfb.build(resourceAsStream); sqlSession = factory.openSession(); } @Test public void testSingleArg(){ // 测试单个基本数据类型作为参数 Emp emp = sqlSession.selectOne("findByEmpno", 7499); System.out.println(emp); } @Test public void testMapArg(){ // 测试Map集合作为参数 Map<String,Object> args = new HashMap<>(); args.put("deptno", 20); args.put("sal", 3000.0); List<Emp> emps = sqlSession.selectList("findEmpByDeptnoAndSal", args); emps.forEach(System.out::println); } @Test public void testEmpArg(){ // 测试Map集合作为参数 Emp arg = new Emp(); arg.setDeptno(10); arg.setSal(2000.0); List<Emp> emps = sqlSession.selectList("findEmpByDeptnoAndSal2", arg); emps.forEach(System.out::println); } @After public void release(){ // 关闭SQLSession sqlSession.close(); } }
-
-
3_sqlSession完成DML所有操作
-
Mapper映射文件
<?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="EmpMapper3"> <!-- 增删方法的返回值类型都是 int resultType 就无需指定了 insert update delete 标签中没有 resultType 但是仍然可以有 paramaterType --> <!-- 增加方法 public int addEmp(Emp emp); --> <insert id="addEmp" parameterType="emp"> insert into emp values(#{empno},#{ename},#{job},#{mgr},#{hiredate},#{sal},#{comm},#{deptno}) </insert> <!--修改 根据工号修改员工姓名 public int updateEmp(Emp emp); --> <update id="updateEmp" parameterType="emp"> update emp set ename = #{ename} where empno = #{empno} </update> <!-- 删除 删除大于给定工号的员工信息 public int deleteEmp(int empno) --> <delete id="deleteEmp" parameterType="int"> delete from emp where empno >= #{empno} </delete> </mapper> -
测试代码
package com.xxx.test; import com.msb.pojo.Emp; 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.After; import org.junit.Before; import org.junit.Test; import java.io.IOException; import java.io.InputStream; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; public class Test4 { private SqlSession sqlSession; @Before public void init(){ SqlSessionFactoryBuilder ssfb = new SqlSessionFactoryBuilder(); InputStream resourceAsStream = null; try { resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml"); } catch (IOException e) { e.printStackTrace(); } SqlSessionFactory factory = ssfb.build(resourceAsStream); sqlSession = factory.openSession(true); } @Test public void testInsert(){ Emp emp = new Emp(null,"按住啦Baby","SALESMAN",7839,new Date(),3100.0, 200.0,10 ); int rows = sqlSession.insert("addEmp", emp); System.out.println(rows); // 手动提交事务 // sqlSession.commit(); /* 增删改 要提交事务 * sqlSession.commit();手动提交事务 * sqlSession = factory.openSession(true); 设置事务自动提交 */ } @Test public void testUpdate(){ Emp emp = new Emp(); emp.setEname("晓明"); emp.setEmpno(7937); int rows = sqlSession.update("updateEmp", emp); System.out.println(rows); } @Test public void testDelete(){ int rows = sqlSession.delete("deleteEmp", 7936); System.out.println(rows); } @After public void release(){ // 关闭SQLSession sqlSession.close(); } }
-
5_MyBatis代理模式开发
-
1_使用Mapper代理方式实现查询
-
项目结构: 注意文件路径和文件位置!!!

-
准备接口和 mapper 映射文件
-
EmpMapper接口
package com.xxx.mapper; import com.xxx.pojo.Emp; import java.util.List; public interface EmpMapper { /** * 该方法用于查询全部的员工信息 * @return 全部员工信息封装的 Emp 对象的 List 集合 */ List<Emp> findAll(); } -
EmpMapper.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.xxx.mapper.EmpMapper"> <!-- 1 接口的名字和 Mapper 映射为文件名字必须保持一致(不包含拓展名) 2 Mapper 映射文件的 namespace 必须是接口的全路径名 3 sql 语句的 id 必须是对应方法的名 4 DeptMapper 映射文件应该和接口编译之后放在同一个目录下 --> <!--List<Emp> findAll();--> <select id="findAll" resultType="emp" > select * from emp </select> </mapper> -
在 sqlMapConfig.xml 核心配置文件中使用包扫描形式加载所有的映射文件
<!-- 加载mapper映射文件 --> <mappers> <!-- 通过类的全路径去找mapper映射文件 --> <mapper class="com.xxx.mapper.EmpMapper"/> </mappers> -
测试代码
package com.xxx.test; import com.xxx.mapper.EmpMapper; import com.xxx.pojo.Dept; import com.xxx.pojo.Emp; 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.After; import org.junit.Before; import org.junit.Test; import java.io.IOException; import java.io.InputStream; import java.util.List; public class Test1 { private SqlSession sqlSession; @Before public void init(){ SqlSessionFactoryBuilder ssfb = new SqlSessionFactoryBuilder(); InputStream resourceAsStream = null; try { resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml"); } catch (IOException e) { e.printStackTrace(); } SqlSessionFactory factory = ssfb.build(resourceAsStream) ; sqlSession = factory.openSession(); } @Test public void testFindAll(){ EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class); List<Emp> emps = empMapper.findAll(); emps.forEach(System.out::println); } @After public void release(){ // 关闭SQLSession sqlSession.close(); } }
-
-
代理模式浅析
-
6_代理模式下开发各种功能
-
1_多种参数传递问题
-
类型
-
接口
package com.xxx.mapper; import com.xxx.pojo.Emp; import org.apache.ibatis.annotations.Param; import java.util.List; import java.util.Map; public interface EmpMapper { /** * 该方法用于查询全部的员工信息 * @return 全部员工信息封装的Emp对象的List集合 */ List<Emp> findAll(); /** * 根据员工编号查询单个员工信息的方法 * @param empno 员工编号 * @return 如果找到了返回Emp对象,找不到返回null */ Emp findByEmpno(int empno); /** * 根据员工编号和薪资下限去查询员工信息 * @param empno 员工编号 * @param sal 薪资下限 * @return 多个Emp对象的List集合 */ List<Emp> findByDeptnoAndSal(@Param("deptno") int deptno,@Param("sal") double sal); List<Emp> findByDeptnoAndSal2(Map<String, Object> map); List<Emp> findByDeptnoAndSal3(Emp emp); List<Emp> findByDeptnoAndSal4(@Param("empa") Emp empa,@Param("empb") Emp empb); } -
mapper映射文件
<?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.xxx.mapper.EmpMapper"> <!-- 1 接口的名字和 Mapper 映射为文件名字必须保持一致(不包含拓展名) 2 Mapper 映射文件的 namespace 必须是接口的全路径名 3 sql 语句的 id 必须是对应方法的名 4 DeptMapper 映射文件应该和接口编译之后放在同一个目录下 --> <!--List<Emp> findAll();--> <select id="findAll" resultType="emp" > select * from emp </select> <!-- 单个基本数据类型作为方法参数 #{}中可以随便写, 遵循见名知意 Emp findByEmpno(int empno); --> <!-- 多个基本数据类型作为方法参数 List<Emp> findByDeptnoAndSal(@Param("detpno") int deptno,@Param("sal") double sal); 方式1 arg* arg0 arg1 arg2 数字是索引,从0开始 方式2 param* param1 param2 param3 数字是编号,从1开始 使用别名 List<Emp> findByDeptnoAndSal(@Param("detpno") int deptno,@Param("sal") double sal); 通过 @Param 注解使用别名之后,就不能再使用 arg* 但是可以继续使用 param* --> <select id="findByDeptnoAndSal" resultType="emp"> <!--select * from emp where deptno =#{arg0} and sal >= #{arg1}--> <!-- select * from emp where deptno =#{param1} and sal >= #{param2}--> <!-- select * from emp where deptno =#{deptno} and sal >= #{sal}--> </select> <!-- 参数是map, {}写键的名字 --> <select id="findByDeptnoAndSal2" resultType="emp" parameterType="map" > <!-- select * from emp where deptno =#{arg0} and sal >= #{arg1} --> <!-- select * from emp where deptno =#{param1} and sal >= #{param2} --> select * from emp where deptno =#{deptno} and sal >= #{sal} </select> <!--单个引用类型,{}中写的使用对象的属性名--> <select id="findByDeptnoAndSal3" resultType="emp" parameterType="emp" > select * from emp where deptno =#{deptno} and sal >= #{sal} </select> <!-- 多个引用类型作为方法参数 List<Emp> findByDeptnoAndSal4(@Param("empa") Emp empa,@Param("empb") Emp empb); 如果用@Param定义了别名,那么就不能使用arg*.属性名,但是可以使用param*.属性名和别名.属性名 --> <select id="findByDeptnoAndSal4" resultType="emp" > <!-- select * from emp where deptno =#{arg0.deptno} and sal >= #{arg1.sal} --> select * from emp where deptno =#{param1.deptno} and sal >= #{param2.sal} <!-- select * from emp where deptno =#{empa.deptno} and sal >= #{empb.sal}--> </select> </mapper> -
测试 代码
package com.xxx.testDemo; import com.xxx.mapper.EmpMapper; import com.xxx.pojo.Emp; import com.xxx.util.SqlSessionUtil; import org.apache.ibatis.session.SqlSession; import java.util.List; public class Test1 { public static void main(String[] args) { SqlSession sqlSession = SqlSessionUtil.getSqlSession(true); /** * 帮助我们生成一个接口下的实现类对象的 */ EmpMapper mapper = sqlSession.getMapper(EmpMapper.class); List<Emp> emps = mapper.getAllEmp(); for(Emp emp:emps) { System.out.println(emp); } // 1单个基本数据类型作为方法参数 Emp emp = mapper.getByEmpno(7902); System.out.println(emp); // 2多个基本数据类型作为方法参数 List<Emp> emps2 = mapper.getByDeptnoAndSal(10, 1500); for(Emp em:emps2) { System.out.println(em); } // 3单个引用类型作为方法参数 Emp condition = new Emp(); condition.setDeptno(10); condition.setSal(1500.0); List<Emp> emps3 = mapper.getByDeptnoAndSal2(condition); for(Emp em:emps3) { System.out.println(em); } // 4多个引用类型作为方法参数 Emp condition1 = new Emp(); condition1.setDeptno(10); Emp condition2 = new Emp(); condition2.setSal(1500.0); List<Emp> emps4 = mapper.getByDeptnoAndSal3(condition1,condition2); for(Emp em:emps4) { System.out.println(em); } sqlSession.close(); } }
-
-
2_模糊查询功能
-
3_主键自增回填
-
概念
-
接口
public interface DeptMapper { int addDept(Dept dept); int addDept2(Dept dept); } -
mapper映射文件
<mapper namespace="com.xxx.mapper.DeptMapper"> <!-- int addDept(Dept dept); useGeneratedKeys="true" 返回数据库帮我们生成的主键 keyProperty="deptno" 生成的主键值用我们dept对象那个属性存储 --> <insert id="addDept" parameterType="dept" useGeneratedKeys="true" keyProperty="deptno"> insert into dept values(null,#{dname},#{loc}) </insert> <insert id="addDept2" parameterType="dept"> <selectKey order="AFTER" keyProperty="deptno" resultType="int"> select @@identity </selectKey> insert into dept values(null,#{dname},#{loc}) </insert> </mapper> -
测试代码
SqlSession sqlSession = SqlSessionUtil.getSqlSession(true); DeptMapper mapper = sqlSession.getMapper(DeptMapper.class); Dept dept = new Dept(null,"AI学院","北京"); int i = mapper.addDept2(dept); System.out.println(i); System.out.println(dept.getDeptno()); sqlSession.close(); -
方式1
-
方式2
-
技术扩展在很多应用场景中需要新增数据后获取到新增数据的主键值,针对这样的需求一般由三种解决方式
-
-
4_实现DML操作
-
EmpMapper接口
/** * 增加员工信息 * @param emp 存储新增员工信息的Emp对象 * @return 对数据库数据产生影响的行数 */ int addEmp(Emp emp); /** * 根据员工编号修改员工姓名的方法 * param empno 要修改的员工编号 * @param ename 修改之后的新的员工名字 * @return 对数据库数据产生影响的行数 */ int updateEnameByEmpno(@Param("empno") int empno, @Param("ename") String ename); /** * 根据员工编号删除员工信息 * @param empno 要删除的员工编号 * @return 对数据库数据产生影响的行数 */ int deleteByEmpno(int empno); -
EmpMapper映射 文件
<!--int addEmp(Emp emp);--> <insert id="addEmp" > insert into emp values(DEFAULT ,#{ename},#{job},#{mgr},#{hiredate},#{sal},#{comm},#{deptno}) </insert> <!--int updateEnameByEmpno(@Param("empno") int empno,@Param("ename") String ename);--> <update id="updateEnameByEmpno" > update emp set ename =#{ename} where empno =#{empno} </update> <!--int deleteByEmpno(int empno);--> <update id="deleteByEmpno" > delete from emp where empno = #{empno} </update> -
测试代码
package com.xxx.test; import com.xxx.mapper.DeptMapper; import com.xxx.mapper.EmpMapper; import com.xxx.pojo.Dept; import com.xxx.pojo.Emp; 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.After; import org.junit.Before; import org.junit.Test; import java.io.IOException; import java.io.InputStream; import java.util.Date; public class Test3 { private SqlSession sqlSession; @Before public void init(){ SqlSessionFactoryBuilder ssfb = new SqlSessionFactoryBuilder(); InputStream resourceAsStream = null; try { resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml"); } catch (IOException e) { e.printStackTrace(); } SqlSessionFactory factory = ssfb.build(resourceAsStream) ; sqlSession = factory.openSession(); } @Test public void testAddEmp(){ EmpMapper mapper = sqlSession.getMapper(EmpMapper.class); mapper.addEmp(new Emp(null, "TOM", "SALESMAN", 7521, new Date(), 2314.0, 100.0, 10)); sqlSession.commit(); } @Test public void testUpdateEnameByEmpno(){ EmpMapper mapper = sqlSession.getMapper(EmpMapper.class); mapper.updateEnameByEmpno(7938, "TOM"); sqlSession.commit(); } @Test public void testDeletByEmpno(){ EmpMapper mapper = sqlSession.getMapper(EmpMapper.class); mapper.deleteByEmpno(7938); sqlSession.commit(); } @After public void release(){ // 关闭SQLSession sqlSession.close(); } }
-
更多推荐
所有评论(0)