Mybatis三种DAO层使用玩法
第一种使用namespace.id来使用Mybatis进行操作
配置类中注册Mapper
<?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>
<settings>
<!--开启驼峰命名转换 form_id -> formId-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<environments default="dev">
<!--开发环境配置-->
<environment id="dev">
<!--事务管理器采用JDBC方式-->
<transactionManager type="JDBC"></transactionManager>
<!--利用Mybatis自带连接池管理连接
<dataSource type="POOLED">-->
<!--MyBatis与Druid的整合-->
<dataSource type="com.xmaven.oa.datasource.DruidDataSourceFactory">
<!--JDBC连接属性-->
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/ambition-oa?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
<!--连接池初始连接数-->
<property name="initialSize" value="20"/>
<!--连接池最大连接数-->
<property name="maxActive" value="20"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mappers/test.xml"/>
<mapper resource="mappers/user.xml"/>
<mapper resource="mappers/rbac.xml"/>
<mapper resource="mappers/employee.xml"/>
<mapper resource="mappers/department.xml"/>
</mappers>
</configuration>
以user.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="usermapper">
<select id="selectByUsername" parameterType="string" resultType="com.xmaven.oa.entity.User">
select * from sys_user where username = #{value}
</select>
</mapper>
编写我们的Mybatis的工具类使用了java8新特性Lambda编写的工具
package com.xmaven.oa.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.Reader;
import java.util.function.Function;
/**
* @ClassName MybatisUtils
* @Description TODO MyBatisUtils工具类,创建全局唯一的SqlSessionFactory对象
* @Author Ambition
* @Date 2021/2/19 13:46
* @Version 1.0.0
**/
public class MybatisUtils {
//利用static(静态)属于类不属于对象,且全局唯一
private static SqlSessionFactory sqlSessionFactory = null;
//利用静态块在初始化类时实例化sqlSessionFactory
static{
Reader reader = null;
try{
reader = Resources.getResourceAsReader("mybatis-config.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
}catch(IOException e){
//初始化错误时,通过抛出异常ExceptionInInitializerError通知调用者
throw new ExceptionInInitializerError(e);
}
}
/**
* 执行SELECT查询SQL
* @param func 要执行查询语句的代码块
* @return 查询结果
*/
public static Object executeQuery(Function<SqlSession,Object> func){
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
Object obj = func.apply(sqlSession);
return obj;
}finally {
sqlSession.close();
}
}
/**
* 执行INSERT/UPDATE/DELETE写操作SQL
* @param func 要执行的写操作代码块
* @return 写操作后返回的结果
*/
public static Object executeUpdate(Function<SqlSession,Object> func){
// 设置sqlsession是否自动提交
SqlSession sqlSession = sqlSessionFactory.openSession(false);
try {
Object obj = func.apply(sqlSession);
sqlSession.commit();
return obj;
}catch (RuntimeException e){
sqlSession.rollback();
throw e;
}finally{
sqlSession.close();
}
}
}
编写dao层
package com.xmaven.oa.dao;
import com.xmaven.oa.entity.User;
import com.xmaven.oa.utils.MybatisUtils;
/**
* @ClassName UserDao
* @Description TODO 用户表Dao
* @Author Ambition
* @Date 2021/2/20 10:33
* @Version 1.0.0
**/
public class UserDao {
/**
* 按照用户名查找用户表
* @param username 用户名
* @return User对象包含的用户信息,null则表示对象不存在
*/
public User SelectByUsername(String username){
User user = (User) MybatisUtils.executeQuery(sqlSession -> sqlSession.selectOne("usermapper.selectByUsername",username));
return user;
}
}
编写Service层
package com.xmaven.oa.service;
import com.xmaven.oa.dao.RbacDao;
import com.xmaven.oa.dao.UserDao;
import com.xmaven.oa.entity.Node;
import com.xmaven.oa.entity.User;
import com.xmaven.oa.service.exception.BussinessException;
import java.util.List;
/**
* @ClassName UserService
* @Description TODO 用户服务
* @Author Ambition
* @Date 2021/2/20 10:38
* @Version 1.0.0
**/
public class UserService {
private UserDao userDao = new UserDao();
/**
* 根据前台输入数据进行登录校验
* @param username 前台输入的用户名
* @param password 前台输入的密码
* @return 校验通过后返回对应User实体类
* @throws BussinessException L001-用户不存在,L002-密码错误
*/
public User checkLogin(String username, String password) {
User user = userDao.SelectByUsername(username);
if (user == null) {
// 抛出用户不存在异常
throw new BussinessException("L001", "用户名不存在");
}
if (!password.equals(user.getPassword())) {
throw new BussinessException("L002", "密码错误");
}
return user;
}
}
第二种就是常用的接口实现
主要是namespace和我们写的接口类关联起来
先编写Dao层
package com.xmaven.oa.dao;
import com.xmaven.oa.entity.Employee;
/**
* @ClassName EmployeeDao
* @Description TODO
* @Author Ambition
* @Date 2021/2/20 15:48
* @Version 1.0.0
**/
public interface EmployeeDao {
public Employee selectById(Long employeeId);
}
以我编写的employee.xml为例解释一下
这个需要把接口名和这个xml的namespace要对应起来
还有里面的id也要和接口的方法名对应起来
<?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需要和包名一致-->
<mapper namespace="com.xmaven.oa.dao.EmployeeDao">
<!-- id与方法名对应
parameterType与方法参数类型对应
resultType与方法返回类型对应
-->
<select id="selectById" parameterType="Long" resultType="com.xmaven.oa.entity.Employee">
select * from adm_employee where employee_id = #{value}
</select>
</mapper>
接下来编写serveice层
package com.xmaven.oa.service;
import com.xmaven.oa.dao.EmployeeDao;
import com.xmaven.oa.entity.Employee;
import com.xmaven.oa.utils.MybatisUtils;
/**
* @ClassName EmployeeService
* @Description TODO 员工服务
* @Author Ambition
* @Date 2021/2/20 15:53
* @Version 1.0.0
**/
public class EmployeeService {
public Employee selectById(Long employeeId) {
return (Employee) MybatisUtils.executeQuery(sqlSession -> {
// 根据传入的接口,自动实现接口的实现类
EmployeeDao employeeDao = sqlSession.getMapper(EmployeeDao.class);
return employeeDao.selectById(employeeId);
});
}
}
注意还有一点,这个也需要注册Mapper
第三种就是我们常用的注解形式
package com.xmaven.mybatis.dao;
import com.xmaven.mybatis.dto.GoodsDTO;
import com.xmaven.mybatis.entity.Goods;
import org.apache.ibatis.annotations.*;
import java.util.List;
public interface GoodsDAO {
@Select("select * from t_goods where current_price between #{min} and #{max} order by current_price limit 0,#{limt}")
public List<Goods> selectByPriceRange(@Param("min") Float min ,@Param("max") Float max ,@Param("limt") Integer limt);
@Insert("INSERT INTO t_goods(title, sub_title, original_cost, current_price, discount, is_free_delivery, category_id) VALUES (#{title} , #{subTitle} , #{originalCost}, #{currentPrice}, #{discount}, #{isFreeDelivery}, #{categoryId})")
//<selectKey>
@SelectKey(statement = "select last_insert_id()" , before = false , keyProperty = "goodsId" , resultType = Integer.class)
public int insert(Goods goods);
@Select("select * from t_goods")
//<resultMap>
@Results({
//<id>
@Result(column = "goods_id" ,property = "goodsId" , id = true) ,
//<result>
@Result(column = "title" ,property = "title"),
@Result(column = "current_price" ,property = "currentPrice")
})
public List<GoodsDTO> selectAll();
}
这个使用这个工具类
package com.xmaven.mybatis.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.Reader;
/**
* MyBatisUtils工具类,创建全局唯一的SqlSessionFactory对象
*/
public class MyBatisUtils {
//利用static(静态)属于类不属于对象,且全局唯一
private static SqlSessionFactory sqlSessionFactory = null;
//利用静态块在初始化类时实例化sqlSessionFactory
static {
Reader reader = null;
try {
reader = Resources.getResourceAsReader("mybatis-config.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
} catch (IOException e) {
e.printStackTrace();
//初始化错误时,通过抛出异常ExceptionInInitializerError通知调用者
throw new ExceptionInInitializerError(e);
}
}
/**
* openSession 创建一个新的SqlSession对象
* @return SqlSession对象
*/
public static SqlSession openSession(){
//默认SqlSession对自动提交事务数据(commit)
//设置false代表关闭自动提交,改为手动提交事务数据
return sqlSessionFactory.openSession(false);
}
/**
* 释放一个有效的SqlSession对象
* @param session 准备释放SqlSession对象
*/
public static void closeSession(SqlSession session){
if(session != null){
session.close();
}
}
}
编写一个测试类
package com.xmaven.mybatis;
import com.xmaven.mybatis.dao.GoodsDAO;
import com.xmaven.mybatis.dto.GoodsDTO;
import com.xmaven.mybatis.entity.Goods;
import com.xmaven.mybatis.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
//JUNIT单元测试类
public class MyBatisTestor {
@Test
public void testSelectByPriceRange() throws Exception {
SqlSession session = null;
try{
session = MyBatisUtils.openSession();
GoodsDAO goodsDAO = session.getMapper(GoodsDAO.class);
List<Goods> list = goodsDAO.selectByPriceRange(100f, 500f, 20);
System.out.println(list.size());
}catch (Exception e){
throw e;
} finally {
MyBatisUtils.closeSession(session);
}
}
/**
* 新增数据
* @throws Exception
*/
@Test
public void testInsert() throws Exception {
SqlSession session = null;
try{
session = MyBatisUtils.openSession();
Goods goods = new Goods();
goods.setTitle("测试商品");
goods.setSubTitle("测试子标题");
goods.setOriginalCost(200f);
goods.setCurrentPrice(100f);
goods.setDiscount(0.5f);
goods.setIsFreeDelivery(1);
goods.setCategoryId(43);
GoodsDAO goodsDAO = session.getMapper(GoodsDAO.class);
//insert()方法返回值代表本次成功插入的记录总数
int num = goodsDAO.insert(goods);
session.commit();//提交事务数据
System.out.println(goods.getGoodsId());
}catch (Exception e){
if(session != null){
session.rollback();//回滚事务
}
throw e;
}finally {
MyBatisUtils.closeSession(session);
}
}
@Test
public void testSelectAll() throws Exception {
SqlSession session = null;
try{
session = MyBatisUtils.openSession();
GoodsDAO goodsDAO = session.getMapper(GoodsDAO.class);
List<GoodsDTO> list = goodsDAO.selectAll();
System.out.println(list.size());
}catch (Exception e){
throw e;
} finally {
MyBatisUtils.closeSession(session);
}
}
}
基本来说接口注解和非注解形式,使用没啥太大差异,看个人喜好
评论区