MyBatis普通模式开发
普通模式,也称为传统DAO模式,就是在传统DAO模式下,定义接口和实现类,如 interface EmpDao class EmpDaoImpl implements EmpDao. 在实现类中,用SQLSession对象调用 select insert delete update 等方法实现.目前极为少见.在传统模式下,我们需要知道SqlSession对象 实现CURD和 参数传递的处理,后续所需表SQL如下:
#创建dept表 CREATE table dept( DEPTON int(2) not NULL, DNAME varchar(14), LOC varchar(13) ) INSERT into dept VALUES(10,'ACCOUNTING','NEW YORK'); INSERT into dept VALUES(20,'RESEARCH','DALLAS'); INSERT into dept VALUES(30,'SALES','CHICAGO'); INSERT into dept VALUES(40,'OPERATIONS','BOSTON'); #创建emp表 CREATE TABLE emp( empno int(4) not null, ename varchar(10), job varchar(9), mgr int(4), hiredate date, sal DECIMAL(7,2), comm DECIMAL(7,2), deptno int(2) ) INSERT into emp values(7369,'SMITH','CLERK',7902,'1980-12-17',800,NULL,20); INSERT into emp values(7499,'ALLEN','SALESMAN',7698,'1981-02-20',1600,300,30); INSERT into emp values(7521,'WARD','SALESMAN',7698,'1981-02-22',1250,500,30); INSERT into emp values(7566,'JONES','MANNAGER',7839,'1981-04-02',2975,NULL,20); INSERT into emp values(7654,'MARTIN','SALESMAN',7698,'1981-09-28',1250,1400,30); INSERT into emp values(7698,'BLAKE','MANNAGER',7839,'1981-05-01',2850,NULL,30); INSERT into emp values(7782,'CLARK','MANNAGER',7839,'1981-06-09',2450,NULL,10); INSERT into emp values(7788,'SCOTT','ANALYST',7566,'1987-07-13',3000,NULL,20); INSERT into emp values(7839,'KING','PRESIDENT',NULL,'1981-11-17',5000,NULL,10); INSERT into emp values(7844,'TURNER','SALESMAN',7698,'1981-09-08',1500,0,30); INSERT into emp values(7876,'ADAMS','CLERK',7788,'1987-07-13',1100,NULL,20); INSERT into emp values(7900,'JAMES','CLERK',7698,'1981-12-03',950,NULL,30); INSERT into emp values(7902,'FORD','ANALYST',7566,'1981-12-03',3000,NULL,20); INSERT into emp values(7934,'MILLER','CLERK',7782,'1982-01-13',1300,NULL,10); #创建salgrade表 CREATE TABLE salgrade( GRADE int(11) not NULL, LOSAL VARCHAR(14), HISAL VARCHAR(13) ) INSERT into salgrade values(1,'700','1200'); INSERT into salgrade values(2,'1201','1400'); INSERT into salgrade values(3,'1401','2000'); INSERT into salgrade values(4,'2001','3000'); INSERT into salgrade values(5,'3001','9999');
一、mybatis查询的三种方式
SqlSessionFactory
- SqlSessionFactory是MyBatis的关键对象,它是个单个数据库映射关系经过编译后的内存镜像。
- SqlSessionFactory对象的实例可以通过SqlSessionFactoryBuilder对象类获得,而SqlSessionFactoryBuilder则可以从XML配置文件或一个预先定制的Configuration的实例构建出SqlSessionFactory的实例。
- 每一个MyBatis的应用程序都以一个SqlSessionFactory对象的实例为核心。
- SqlSessionFactory是线程安全的,SqlSessionFactory一旦被创建,应该在应用执行期间都存在。在应用运行期间不要重复创建多次,建议使用单例模式。
- SqlSessionFactory是创建SqlSession的工厂。
SqlSession
- SqlSession是MyBatis的关键对象,是执行持久化操作的独享,类似于JDBC中的Connection。
- 它是应用程序与持久层之间执行交互操作的一个单线程对象,也是MyBatis执行持久化操作的关键对象。
- SqlSession对象完全包含以数据库为背景的所有执行SQL操作的方法,它的底层封装了JDBC连接,可以用SqlSession实例来直接执行被映射的SQL语句。
- 每个线程都应该有它自己的SqlSession实例。
- SqlSession的实例不能被共享,同时SqlSession也是线程不安全的,绝对不能讲SqlSeesion实例的引用放在一个类的静态字段甚至是实例字段中。也绝不能将SqlSession实例的引用放在任何类型的管理范围中,比如Servlet当中的HttpSession对象中。
- 使用完SqlSeesion之后关闭Session很重要,应该确保使用finally块来关闭它。
SqlSession对象本身API中就已经提供了三个查询方法,分别能够实现如下查询方式
- selectOne:返回单个对象
- selectList:返回对象List集合
- selectMap:返回对象Map集合
1.1.准备emp表对应实体类
在com.augus.pojo包下创建实体类如下:
@Data @AllArgsConstructor @NoArgsConstructor public class Emp implements Serializable { private Integer empno; private String ename; private String job; private String mgr; private Date hiredate; private Double sal; private Double comm; private Integer deptno; }
1.2.创建EmpMapper.xml映射文件
这里注意传统模式下是不会开发接口,只会在创建映射文件如下:在com.augus.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"> <!-- namespace这里需要设置和接口类的路径 可以理解成要实现的SQL定义在那个接口文件中 --> <mapper namespace="EmpMapper"> <!-- 要实现查询empno为7654的员工信息 --> <select id="findEmpNo" resultType="emp"> select * from emp where empno=7566 </select> <!-- 查询所有的员工信息,放在集合中 List<Emp> findAllEmp(); --> <select id="findAllEmp" resultType="emp"> select * from emp </select> <!-- 查询所有的员工信息,结果放在集合中 List<Map> findAllMap(); resultType="map" 指定结果以集合的形式存放 --> <select id="findAllMap" resultType="map"> select * from emp </select> </mapper>
1.3.在sqlMapConfig.xml中配置映射文件
特别注意的是需要在sqlMapConfig.xml中配置引入mapper文件,必须使用resource标签实现
<?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 resource="jdbc.properties"></properties> <settings> <setting name="logImpl" value="LOG4J2"/> </settings> <typeAliases> <!-- 如下每一个实体类都起别名,那么实体类特别的就很麻烦,所以通过, 包扫描的方式即可解决。会自动扫描某个包下面的所有实体类,默认 用类名的小写作为应用时的类名 --> <!--<typeAlias type="com.augus01.pojo.Dept" alias="dept"></typeAlias>--> <package name="com.augus.pojo"/> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <!--指定连接数据库的信息,数据库服务器ip、端口、用户名、密码--> <property name="driver" value="${jdbc_driver}"/> <property name="url" value="${jdbc_url}"/> <property name="username" value="${jdbc_username}"/> <property name="password" value="${jdbc_password}"/> </dataSource> </environment> </environments> <!--加载mapper映射文件--> <mappers> <mapper resource="com/augus/mapper/EmpMapper.xml"/> </mappers> </configuration>
截图如下:

1.4.编写测试代码如下
这里编写的是代码基于Junit5进行测试
public class Test1 { private static SqlSession sqlSession; @BeforeAll public static void init() throws IOException { //指定加载的xml配置文件 InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml"); /** * SqlSessionFactoryBuilder主要是提供了根据字节流、字符流以及配置参数这三个参数组成的各种build方法,最终会调用上的build方法。 * SqlSessionFactoryBuilder的 build()方法用于创建 SqlSessionFactory 的实例。SqlSessionFactory 用于创建 SqlSession 实例。 */ SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream); /** * SqlSession是MyBatis的关键对象,是执行持久化操作的对象,类似于JDBC中的Connection。 * 它是应用程序与持久存储层之间执行交互操作的一个单线程对象,也是MyBatis执行持久化操作的关键对象。 * SqlSession对象完全包含以数据库为背景的所有执行SQL操作的方法,它的底层封装了JDBC连接,可以用SqlSession实例来直接执行已映射的SQL语句。 * 每个线程都应该有它自己的SqlSession实例。SqlSession的实例不能被共享,也是线程不安全的,绝对不能将SqlSession 实例的引用放在一个类的静态字段甚至是实例字段中。也绝不能将SqlSession实例的引用放在任何类型的管理范围中,比如Serlvet当中的HttpSession 对象中。使用完SqlSession之后关闭Session很重要,应该确保使用finally块来关闭它。 */ sqlSession = build.openSession(); } @Test public void testFindEmpOne(){ Emp emp = sqlSession.selectOne("findEmpNo"); System.out.println(emp); } @Test public void testFindEmpAll(){ List<Emp> findAllEmp = sqlSession.selectList("findAllEmp"); for (Emp emp : findAllEmp) { System.out.println(emp); } } @Test public void testFindEmpMapAll(){ //以empno字段作为键,每一条结果作为值,键的名字必须和表字段大小写保持一致 Map<Integer,Emp> findAllMap = sqlSession.selectMap("findAllMap","empno"); //获取键 Set<Integer> integers = findAllMap.keySet(); //根据键取值 for (Integer integer : integers) { //根据键取值 Object emp = findAllMap.get(integer); System.out.println("键为:"+integer+",值为:"+emp); } } }
二、mybatis参数传递的三种方式
对应SQL中进行参数化时设置参数而言,mybatis提供了三种方式:
- 单个基础数据类型作为参数
- 多个基础数据类型的map 集合作为参数
- 引用类型作为参数
1.创建EmpMapper2.xml映射文件
在里面编写对应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="EmpMapper2"> <!-- 根据编号查询员工信息 id="findEmpByEmpNo" 名称: resultType="emp" 返回的类型 parameterType="integer":参数的类型 在SQL语句上可以使用${} #{} 代表参数的占位,如果参数是单个基本数据类型,{}中名字可以随便写,见名知意 ${} 代表mybatis底层使用Statment语句对象,参数是以字符串拼接的形式设置 #{} 代表mybatis底层使用的preparedStatment语句对象,参数使用?作为占位符处理 常用方式(推荐) --> <select id="findEmpByEmpNo" resultType="emp" parameterType="integer"> select * from emp where empno=#{empno} </select> <!-- 多个基础数据类型的map 集合作为参数,根据部门号和最低薪资的进行查询 参数为map集合,所以parameterType="map" --> <select id="findEmpByDeptNoAndSal1" resultType="emp" parameterType="map"> select * from emp where deptno=#{deptno} and sal=#{sal} </select> <!-- 引用类型作为参数:参数以Emp对象属性的值传入 --> <select id="findEmpByDeptNoAndSal2" resultType="emp" parameterType="emp"> select * from emp where deptno=#{deptno} and sal=#{sal} </select> </mapper>
2.在sqlMapConfig.xml中设置加载EmpMapper2.xml文件
<mapper resource="com/augus/mapper/EmpMapper2.xml"/>
如下图所示:

3.测试代码
创建测试代码Test2,如下:
public class Test2 { private static SqlSession sqlSession; @BeforeAll public static void init() throws IOException { //指定加载的xml配置文件 InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml"); /** * SqlSessionFactoryBuilder主要是提供了根据字节流、字符流以及配置参数这三个参数组成的各种build方法,最终会调用上的build方法。 * SqlSessionFactoryBuilder的 build()方法用于创建 SqlSessionFactory 的实例。SqlSessionFactory 用于创建 SqlSession 实例。 */ SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream); /** * SqlSession是MyBatis的关键对象,是执行持久化操作的对象,类似于JDBC中的Connection。 * 它是应用程序与持久存储层之间执行交互操作的一个单线程对象,也是MyBatis执行持久化操作的关键对象。 * SqlSession对象完全包含以数据库为背景的所有执行SQL操作的方法,它的底层封装了JDBC连接,可以用SqlSession实例来直接执行已映射的SQL语句。 * 每个线程都应该有它自己的SqlSession实例。SqlSession的实例不能被共享,也是线程不安全的,绝对不能将SqlSession 实例的引用放在一个类的静态字段甚至是实例字段中。也绝不能将SqlSession实例的引用放在任何类型的管理范围中,比如Serlvet当中的HttpSession 对象中。使用完SqlSession之后关闭Session很重要,应该确保使用finally块来关闭它。 */ sqlSession = build.openSession(); } @Test public void findEmpByEmpNo(){ Emp emp = sqlSession.selectOne("findEmpByEmpNo",7782); System.out.println(emp); } /** * 多个基础数据类型的map 集合作为参数 */ @Test public void testFindEmpByDeptNoAndSal1(){ //参数作为map集合传入 HashMap<String, Object> stringObjectHashMap = new HashMap<>(); //设置键值对象 stringObjectHashMap.put("deptno",30); stringObjectHashMap.put("sal",2850.00); //执行sql,传入map集合组合的参数 List<Emp> emps = sqlSession.selectList("findEmpByDeptNoAndSal1", stringObjectHashMap); for (Emp emp : emps) { System.out.println(emp); } } /** * 引用类型作为参数 */ @Test public void testFindEmpByDeptNoAndSal2(){ //创建Emp对象,组合参数 Emp emp = new Emp(); //设置属性 emp.setDeptno(30); emp.setSal(2850.00); //执行sql List<Emp> emps = sqlSession.selectList("findEmpByDeptNoAndSal2", emp); //输出 for (Emp emp1 : emps) { System.out.println(emp1); } } }
执行如下:

三、mybatis完成DML全部操作
1.创建EmpMapper3.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="EmpMapper3"> <!-- 注意增加、删除、修改操作返回的都是int类型,表示操作的数据量 所以resltType则无序指定 insert、update、delete标签中没有resultType属性,但是可以设置paramaterType --> <!--增加--> <insert id="addEmp" parameterType="emp"> insert into emp values (#{empno},#{ename},#{job},#{mgr},#{hiredate},#{sal},#{comm},#{deptno}) </insert> <!--修改 根据员工编号,修改员工姓名 --> <update id="updateEmpNameByEmpNo" parameterType="emp"> update emp set ename=#{ename} where empno=#{empno} </update> <!-- 删除 根据员工编号删除员工信息 --> <delete id="deleteEmpByEmpNO" parameterType="integer"> delete from emp where empno>#{empno} </delete> </mapper>
2.在sqlMapConfig.xml中设置加载EmpMapper2.xml文件
在配置文件中添加映射文件:
<mapper resource="com/augus/mapper/EmpMapper3.xml"/>
如下图:

3.测试代码
创建测试类,进行测试如下:
public class Test3 { private static SqlSession sqlSession; @BeforeAll public static void init() throws IOException { //指定加载的xml配置文件 InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml"); /** * SqlSessionFactoryBuilder主要是提供了根据字节流、字符流以及配置参数这三个参数组成的各种build方法,最终会调用上的build方法。 * SqlSessionFactoryBuilder的 build()方法用于创建 SqlSessionFactory 的实例。SqlSessionFactory 用于创建 SqlSession 实例。 */ SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream); /** * SqlSession是MyBatis的关键对象,是执行持久化操作的对象,类似于JDBC中的Connection。 * 它是应用程序与持久存储层之间执行交互操作的一个单线程对象,也是MyBatis执行持久化操作的关键对象。 * SqlSession对象完全包含以数据库为背景的所有执行SQL操作的方法,它的底层封装了JDBC连接,可以用SqlSession实例来直接执行已映射的SQL语句。 * 每个线程都应该有它自己的SqlSession实例。SqlSession的实例不能被共享,也是线程不安全的,绝对不能将SqlSession 实例的引用放在一个类的静态字段甚至是实例字段中。也绝不能将SqlSession实例的引用放在任何类型的管理范围中,比如Serlvet当中的HttpSession 对象中。使用完SqlSession之后关闭Session很重要,应该确保使用finally块来关闭它。 */ sqlSession = build.openSession(); } /** * 新增 */ @Test public void testAddEmp(){ //创建Emp对象,作为参数传入 Emp emp = new Emp(7910, null, "张飞", 7965, new Date(), 8800.0, 200.0, 20); //执行sql int result = sqlSession.insert("addEmp", emp); //注意在增删改对数据作出影响的情况,必须提交事务 sqlSession.commit(); System.out.println(result); } /** * 修改 */ @Test public void testUpdateEmpNameByEmpNo(){ //创建Emp对象,组合参数 Emp emp = new Emp(); //设置属性 emp.setEmpno(7910); emp.setEname("李敏"); //执行sql int result = sqlSession.update("updateEmpNameByEmpNo", emp); //注意在增删改对数据作出影响的情况,必须提交事务 sqlSession.commit(); System.out.println(result); } /** * 删除编号大于7905的员工信息 */ @Test public void testDeleteEmpByEmpNO(){ int result = sqlSession.delete("deleteEmpByEmpNO", 7905); //注意在增删改对数据作出影响的情况,必须提交事务 sqlSession.commit(); System.out.println(result); } }

浙公网安备 33010602011771号