一、使用Mapper代理方式实现查询
首先创建一个Mapper目录下的EmpMapper接口,在resource目录下创建EmpMapper.xml映射文件,并在SqlSessionFactory.xml进行Mapper文件扫描
<!--添加对应的mapper映射文件--><mappers><mapper class="com.xiaohui.mapper.EmpMapper"></mapper></mappers>
EmpMapper.java
package com.xiaohui.mapper;import com.xiaohui.entity.Emp;import java.util.List;public interface EmpMapper {/*** @功能描述:查询全部的员工信息* @Param* @return 全部员工信息封装的Emp对象的list集合*/List<Emp> findAll();}
EmpMapper.xml
<mapper namespace="com.xiaohui.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>
测试代码:
//查询全部员工信息@Testpublic void findAllTest(){EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);List<Emp> empMapperAll = empMapper.findAll();empMapperAll.forEach(System.out::println);}
结果:
DEBUG - Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@247310d0]DEBUG - ==> Preparing: select * from empDEBUG - ==> Parameters:DEBUG - <== Total: 14Emp(empno=7369, ename=SMITH, job=CLERK, mgr=7902, hiredate=Wed Dec 17 00:00:00 CST 1980, sal=800.0, comm=null, deptno=20)Emp(empno=7499, ename=ALLEN, job=SALESMAN, mgr=7698, hiredate=Fri Feb 20 00:00:00 CST 1981, sal=1600.0, comm=300.0, deptno=30)Emp(empno=7521, ename=WARD, job=SALESMAN, mgr=7698, hiredate=Sun Feb 22 00:00:00 CST 1981, sal=1250.0, comm=500.0, deptno=30)Emp(empno=7566, ename=JONES, job=MANAGER, mgr=7839, hiredate=Thu Apr 02 00:00:00 CST 1981, sal=2975.0, comm=null, deptno=20)Emp(empno=7654, ename=MARTIN, job=SALESMAN, mgr=7698, hiredate=Mon Sep 28 00:00:00 CST 1981, sal=1250.0, comm=1400.0, deptno=30)DEBUG - Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@247310d0]DEBUG - Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@247310d0]DEBUG - Returned connection 611520720 to pool.
二、接口代理下的参数问题
单个基本数据类型传入Mapper映射文件进行单条数据查询,只需要传入一个数据类型的数据进行查询就行了
当多个基本数据类型参数进行查询时,有以下几种方式进行参数传递
方式1 arg* arg0 arg1 arg2 数字是索引,从0开始
<select id="findByDeptnoAndSal" resultType="emp">select * from emp Where deptno = #{arg0} and sal >= #{arg1}</select>
测试代码:
@Testpublic void testFindByEmpnoAndSal(){//获取接口EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);List<Emp> byEmpnoAndSal = empMapper.findByDeptnoAndSal(20, 3000.0);byEmpnoAndSal.forEach(System.out::println);}
结果:
DEBUG - ==> Preparing: select * from emp Where deptno = ? and sal >= ?DEBUG - ==> Parameters: 20(Integer), 3000.0(Double)DEBUG - <== Total: 2Emp(empno=7788, ename=SCOTT, job=ANALYST, mgr=7566, hiredate=Sun Apr 19 00:00:00 CDT 1987, sal=3000.0, comm=null, deptno=20)Emp(empno=7902, ename=FORD, job=ANALYST, mgr=7566, hiredate=Thu Dec 03 00:00:00 CST 1981, sal=3000.0, comm=null, deptno=20)DEBUG - Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@6be968ce]
方式2 param* param1 param2 param3 数字是编号,从1开始
<select id="findByDeptnoAndSal" resultType="emp">select * from emp Where deptno = #{param1} and sal >= #{param2}</select>
结果:
DEBUG - ==> Preparing: select * from emp Where deptno = ? and sal >= ?DEBUG - ==> Parameters: 20(Integer), 3000.0(Double)DEBUG - <== Total: 2Emp(empno=7788, ename=SCOTT, job=ANALYST, mgr=7566, hiredate=Sun Apr 19 00:00:00 CDT 1987, sal=3000.0, comm=null, deptno=20)Emp(empno=7902, ename=FORD, job=ANALYST, mgr=7566, hiredate=Thu Dec 03 00:00:00 CST 1981, sal=3000.0, comm=null, deptno=20)DEBUG - Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@609e8838]
方式3 使用@Param注解(别名)来作为方法参数传递
通过@Param注解使用别名之后,就不能再使用arg 但是可以继续使用param(方式2)
List<Emp> findByDeptnoAndSal(@Param("deptno") int deptno,@Param("sal") double sal);
<select id="findByDeptnoAndSal" resultType="emp">select * from emp Where deptno = #{deptno} and sal >= #{sal}</select>
使用Map集合作为方法参数传递
使用Map集合的方式进行参数的传递时,在mapper映射文件中指定接受数据类型是map,并使用对应的键作为参数占位进行sql操作
List<Emp> findByDeptnoAndSalMap(Map<String,Object> map);
<select id="findByDeptnoAndSalMap" resultType="emp" parameterType="map">select * from emp Where deptno = #{deptno} and sal >= #{sal}</select>
测试代码:
//Map形式进行查询某个员工信息@Testpublic void testFindByEmpnoAndSalMap(){//获取接口EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);Map<String,Object> map = new HashMap<>();map.put("deptno",20);map.put("sal",3000.0);List<Emp> byEmpnoAndSal = empMapper.findByDeptnoAndSalMap(map);byEmpnoAndSal.forEach(System.out::println);}
使用引用类型作为方法参数传递
使用对象其中的属性作为参数传递时,在Mapper映射文件中指定接受类型是emp对象,并使用emp对象中的属性名作为参数占位
单个引用类型作为方法参数传递
List<Emp> findByDeptnoAndSalEmp(Emp emp);
<select id="findByDeptnoAndSalEmp" resultType="emp" parameterType="emp">select * from emp Where deptno = #{deptno} and sal >= #{sal}</select>
测试代码:
//对象形式进行查询某个员工信息@Testpublic void testFindByEmpnoAndSalEmp(){//获取接口EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);Emp emp = new Emp();emp.setDeptno(20);emp.setSal(3000.0);List<Emp> byEmpnoAndSal = empMapper.findByDeptnoAndSalEmp(emp);byEmpnoAndSal.forEach(System.out::println);}
多个引用类型作为方法参数传递
当使用多个引用类型时,Mapper映射文件中可以使用arg.xxx, param.xxx 、@Param注解(别名).xxx来进行参数占位
//List<Emp> findByDeptnoAndSalEmp(Emp emp1,Emp emp2);List<Emp> findByDeptnoAndSalEmpList(@Param("emp1") Emp emp1,@Param("emp2") Emp emp2);
<select id="findByDeptnoAndSalEmpList" 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 = #{emp1.deptno} and sal >= #{emp2.sal}</select>
测试代码:
@Testpublic void testFindByEmpList(){//获取接口EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);Emp emp1 = new Emp();emp1.setDeptno(20);Emp emp2 = new Emp();emp2.setSal(3000.0);List<Emp> byEmpnoAndSal = empMapper.findByDeptnoAndSalEmpList(emp1,emp2);byEmpnoAndSal.forEach(System.out::println);}
模糊查询方式
List<Emp> findByEname( String name);
<select id="findByEname" resultType="emp">select * from emp where ename like concat('%',#{ename},'%')</select>
测试代码:
@Testpublic void testFindByEname(){//获取接口EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);List<Emp> byEname = empMapper.findByEname("a");byEname.forEach(System.out::println);}
结果:
DEBUG - Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7ae0a9ec]DEBUG - ==> Preparing: select * from emp where ename like ?DEBUG - ==> Parameters: %a%(String)DEBUG - <== Total: 7DEBUG - Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7ae0a9ec]
主键自增回填
当使用增加数据时,如果主键没有设置自增并且作为其他表的外链接进行数据操作时会有错误发生,解决办法是在inser标签中增加以 下面两个就可以解决
useGeneratedKeys=”true” 返回数据库帮我们生成的主键
keyProperty=”deptno” 生成的主键值用我们dept对象那个属性存储
<mapper namespace="com.xiaohui.mapper.DeptMapper"><insert id="addDept" parameterType="dept" useGeneratedKeys="true" keyProperty="deptno">insert into dept values (DEFAULT ,#{dname},#{loc} )</insert></mapper>
测试代码:
@Testpublic void testAddDept(){DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);Dept dept = new Dept(null, "JAva", "BOSTON");System.out.println(dept.getDeptno());mapper.addDept(dept);sqlSession.commit();System.out.println(dept.getDeptno());}
结果
DEBUG - Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@514646ef]DEBUG - ==> Preparing: insert into dept values (DEFAULT ,?,? )DEBUG - ==> Parameters: JAva(String), BOSTON(String)DEBUG - <== Updates: 1DEBUG - Committing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@514646ef]null42DEBUG - Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@514646ef]
第二种方式进行主键自增回填
<mapper namespace="com.xiaohui.mapper.DeptMapper"><insert id="addDept2" parameterType="dept"><selectKey order="AFTER" keyProperty="deptno" resultType="int">select @@identity</selectKey>insert into dept values(null,#{dname},#{loc})</insert></mapper>
结果
DEBUG - Checking to see if class com.xiaohui.mapper.EmpMapper matches criteria [is assignable to Object]nullDEBUG - Opening JDBC ConnectionDEBUG - Created connection 611520720.DEBUG - Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@247310d0]DEBUG - ==> Preparing: insert into dept values(null,?,?)DEBUG - ==> Parameters: JAva(String), BOSTON(String)DEBUG - <== Updates: 1DEBUG - ==> Preparing: select @@identityDEBUG - ==> Parameters:DEBUG - <== Total: 1DEBUG - Committing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@247310d0]43DEBUG - Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@247310d0]DEBUG - Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@247310d0]DEBUG - Returned connection 611520720 to pool.Process finished with exit code 0
三、接口代理下实现CRUD操作
public interface EmpMapper {/*** 增加员工信息*/int addEmp(Emp emp);/*** 根据员工编号修改员工姓名的方法*/int updateEnameByEmpno(@Param("empno") int empno,@Param("ename") String ename);/*** 根据员工编号删除员工信息*/int deleteByEmpno(int empno);}
<!--int addEmp(Emp emp);--><insert id="addEmp" parameterType="emp">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);--><delete id="deleteByEmpno">delete from emp where empno =#{empno}</delete>
测试代码
@Testpublic 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();}@Testpublic void testUpdateEnameByEmpno(){EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);mapper.updateEnameByEmpno(7935, "TOM");sqlSession.commit();}@Testpublic void testDeletByEmpno(){EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);mapper.deleteByEmpno(7935);sqlSession.commit();}
结果就是对该数据进行增删改的操作
