使用Mybatis开发Dao,通常有两个方法,即
- 原始Dao开发方法
- Mapper代理开发方法
原始DAO开发方式
原始Dao开发方法需要程序员编写Dao接口和Dao实现类,无非就是在Dao实现类里面调用映射文件里面定义的sql而已。
工具类
package org.example.utils;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 java.io.IOException;
import java.io.InputStream;/*** Mybatis工具类*/
public class MybatisUtil {private MybatisUtil(){}/*** SqlSessionFactory的最佳使用范围是整个应用运行期间,一旦创建后可以重复使用,通常以单例模式管理*/private static SqlSessionFactory sqlSessionFactory = null;static {//1.读取Mybatis的全局配置文件try {InputStream is = Resources.getResourceAsStream("mybatis-config.xml");//2.获取SqlSessionFactory//SqlSessionFacoty一旦创建完成就不需要SqlSessionFactoryBuilder对象了sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);} catch (IOException e) {throw new RuntimeException(e);}}/*** 获取SqlSession的方法*/public static SqlSession getSession(){return sqlSessionFactory.openSession(true);} //true表示自动提交事务}
实体类
package org.example.entity;/**
* Dept实体类
*/
public class Dept {
private Integer deptno;
private String dname;
private String loc;
public Integer getDeptno() {
return deptno;
}
public void setDeptno(Integer 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;}@Overridepublic String toString() {return "Dept{" +"deptno=" + deptno +", dname='" + dname + '\'' +", loc='" + loc + '\'' +'}';}
}
接口
package org.example.dao;import org.example.entity.Dept;
import java.util.List;public interface DeptDao {/*** 查询所有部门* @return*/List<Dept> select();/*** 根据id查询部门信息* @param deptno* @return*/Dept selectById(Integer deptno);/*** 新增部门信息* @param dept* @return*/int insert(Dept dept);/*** 更新部门信息* @param dept* @return*/int update(Dept dept);/*** 根据id删除部门信息* @param deptno* @return*/int delete(Integer deptno);
}
实现类
package org.example.dao.impl;import org.apache.ibatis.session.SqlSession;
import org.example.dao.DeptDao;
import org.example.entity.Dept;
import org.example.utils.MybatisUtil;import java.util.List;public class DeptDaoImpl implements DeptDao {@Overridepublic List<Dept> select() {SqlSession sqlSession = MybatisUtil.getSession();List<Dept> depts = sqlSession.selectList("dept.select");sqlSession.close();return depts;}@Overridepublic Dept selectById(Integer deptno) {SqlSession sqlSession = MybatisUtil.getSession();Dept dept = sqlSession.selectOne("dept.selectById", 10);sqlSession.close();return dept;}@Overridepublic int insert(Dept dept) {SqlSession sqlSession = MybatisUtil.getSession();int result = sqlSession.insert("dept.insert", dept);sqlSession.close();return result;}@Overridepublic int update(Dept dept) {SqlSession sqlSession = MybatisUtil.getSession();int result = sqlSession.update("dept.update", dept);sqlSession.close();return result;}@Overridepublic int delete(Integer deptno) {SqlSession sqlSession = MybatisUtil.getSession();int result = sqlSession.delete("dept.delete", deptno);sqlSession.close();return result;}
}
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="dept"><select id="select" resultType="org.example.entity.Dept">select deptno,dname,loc from dept</select><select id="selectById" parameterType="java.lang.Integer"resultType="org.example.entity.Dept">select deptno,dname,loc from dept where deptno=#{deptno}</select><insert id="insert" parameterType="org.example.entity.Dept">insert into dept(dname,loc) values(#{dname},#{loc})</insert><update id="update" parameterType="org.example.entity.Dept">update dept set dname=#{dname},loc=#{loc} where deptno=#{deptno}</update><delete id="delete" parameterType="java.lang.Integer">delete from dept where deptno=#{deptno}</delete>
</mapper>
在核心配置文件中加载mapper文件
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration><properties resource=""/><typeAliases><package name=""/></typeAliases><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/ssm"/><property name="username" value="root"/><property name="password" value="root"/></dataSource></environment></environments><mappers><mapper resource="mapper/DeptMapper.xml"/></mappers>
</configuration>
测试
package org.example;import org.example.dao.DeptDao;
import org.example.dao.impl.DeptDaoImpl;
import org.example.entity.Dept;
import org.junit.Test;import java.util.List;public class DaoTest {private DeptDao deptDao = new DeptDaoImpl();@Testpublic void testSelect() {List<Dept> list = deptDao.select();for (Dept dept : list) {System.out.println(dept);}}@Testpublic void testSelectById() {Dept dept = deptDao.selectById(20);System.out.println(dept);}@Testpublic void testInsert() {Dept dept = new Dept();dept.setDname("企划部");dept.setLoc("深圳");int result = deptDao.insert(dept);System.out.println("影响数据库的条数:" + result);}@Testpublic void testUpdate() {Dept dept = new Dept();dept.setDeptno(41);dept.setDname("生产部");dept.setLoc("杭州");int result = deptDao.update(dept);System.out.println("影响数据库的条数:" + result);}@Testpublic void testDelete() {int result = deptDao.delete(41);System.out.println("影响数据库的条数:" + result);}
}
原始DAO开发问题
- Dao接口实现类方法中存在大量模板方法,设想能否将这些代码提取出来,大大减轻程序员的工作量。
- 调用sqlSession的数据库操作方法需要指定statement的id,这里存在硬编码,不利于开发维护。
- 调用SqlSession方法时传入的变量,由于SqlSession方法使用泛型,即使变量类型传入错误,在编译阶段也不报错,不利于程序员开发。
注:原始Dao开发和我们Web阶段讲解的Dao开发基本类似,都是有Dao接口和Dao实现类,无非Web阶段的Dao实现类中通过DBUtils来操作SQL;现在Mybatis的原始Dao开发,把SQL分离出去了,写在的XML映射文件里面而已。
Mapper代理方式
Mapper代理开发方式只需要程序员编写Mapper接口(相当于Dao接口),由MyBatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。
程序员编写Mapper接口需要遵循一些开发规范,MyBatis可以自动生成Mapper接口实现类代理对象。
开发规范
1、Mapper.xml文件中的namespace与mapper接口的类路径相同。
2、Mapper.xml中定义的每个标签的id与Mapper接口方法名相同。
3、Mapper.xml中定义的每个sql的parameterType的类型与Mapper接口方法的参数类型相同。
4、Mapper.xml中定义的每个sql的resultType的类型与Mapper接口方法返回值类型相同。
注:Mapper.xml映射文件最好和Mapper接口名称一致。
实体类
package org.example.entity;import java.util.Date;public class Emp {private Integer empno;private String ename;private String job;private Integer mgr;private Date hiredate;private Double sal;private Double comm;private Integer deptno;public Integer getEmpno() {return empno;}public void setEmpno(Integer empno) {this.empno = empno;}public String getEname() {return ename;}public void setEname(String ename) {this.ename = ename;}public String getJob() {return job;}public void setJob(String job) {this.job = job;}public Integer getMgr() {return mgr;}public void setMgr(Integer mgr) {this.mgr = mgr;}public Date getHiredate() {return hiredate;}public void setHiredate(Date hiredate) {this.hiredate = hiredate;}public Double getSal() {return sal;}public void setSal(Double sal) {this.sal = sal;}public Double getComm() {return comm;}public void setComm(Double comm) {this.comm = comm;}public Integer getDeptno() {return deptno;}public void setDeptno(Integer deptno) {this.deptno = deptno;}@Overridepublic String toString() {return "Emp{" +"empno=" + empno +", ename='" + ename + '\'' +", job='" + job + '\'' +", mgr=" + mgr +", hiredate=" + hiredate +", sal=" + sal +", comm=" + comm +", deptno=" + deptno +'}';}
}
Mapper接口
Mapper接口相当于我们之前写的Dao接口,只是在Mybatis里面我们习惯这么写而已。
package org.example.mapper;import org.example.entity.Emp;import java.util.List;/** Mapper接口相当于我们之前写的Dao接口,只是在Mybatis里面我们习惯这么写而已。*/
public interface EmpMapper {List<Emp> select();Emp selectById(Integer empno);/*** 方法返回值为void,表示SqlSession对象中insert,update,delete方法的返回值不做任何处* 理。* @param emp*/void insert(Emp emp);/*** 方法返回值为int类型,表示SqlSession对象中insert,update,delete方法的返回值直接返* 回。* @param emp*/int update(Emp emp);/*** 方法返回值为boolean类型,表示根据SqlSession对象中的insert,update,delete方法返回* 值(影响数据库的条数)判断操作是否成功,如果影响数据库的条数大于0条,表示成功,否* 则表示失败。* @param empno* @return*/boolean delete(Integer empno);
}
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="org.example.mapper.EmpMapper"><select id="select" resultType="org.example.entity.Emp">select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp</select><select id="selectById" parameterType="java.lang.Integer"resultType="org.example.entity.Emp">select empno,ename,job,hiredate,mgr,sal,comm,deptno from emp whereempno=#{empno}</select><insert id="insert" parameterType="org.example.entity.Emp">insert into emp(ename,job,mgr,hiredate,sal,comm,deptno)values(#{ename},#{job},#{mgr},#{hiredate},#{sal},#{comm},#{deptno})</insert><update id="update" parameterType="org.example.entity.Emp">update emp setename=#{ename},job=#{job},mgr=#{mgr},hiredate=#{hiredate},sal=#{sal},comm=#{comm},deptno=#{deptno}where empno=#{empno}</update><delete id="delete" parameterType="java.lang.Integer">delete from emp where empno=#{empno}</delete>
</mapper>
在核心配置文件中加载mapper文件
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration><properties resource=""/><typeAliases><package name=""/></typeAliases><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/ssm"/><property name="username" value="root"/><property name="password" value="root"/></dataSource></environment></environments><mappers><mapper resource="mapper/EmpMapper.xml"/></mappers>
</configuration>
测试
package org.example;import org.apache.ibatis.session.SqlSession;
import org.example.entity.Emp;
import org.example.mapper.EmpMapper;
import org.example.utils.MybatisUtil;
import org.junit.Test;import java.util.List;public class MapperTest {@Testpublic void testMapper(){SqlSession sqlSession = MybatisUtil.getSession();//获取Mapper接口的代理对象(实现类对象)//告诉mtbatis生成哪个接口的实现类对象EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);List<Emp> emps = empMapper.select();for (Emp emp:emps){System.out.println(emp);}}
}
Mybatis官方推荐使用mapper代理方式开发mapper接口,程序员不用编写mapper接口实现类,使用mapper代理方法时,输入参数可以使用pojo包装对象或map对象,保证dao的通用性。