mybatis--开发Dao--原始dao方式和Mapper代理方式

20 篇文章 0 订阅

Mybatis开发dao

Mybatis在项目中主要使用的地方就是开发dao(数据访问层),

有两种方式:原始dao开发方式mapper代理开发方式(推荐)

需求:

1、 根据用户ID来查询用户信息;

2、 根据用户名称来模糊查询用户信息列表;

3、添加用户;
 

一、原始dao开发方式

1、思路

需要写dao接口和dao实现类。

2、编程步骤

1、  根据需求创建po类

2、  编写全局配置文件

3、  根据需求编写映射文件

4、  加载映射文件

5、  编写dao接口

6、  编写dao实现类

7、  编写测试代码

 

3、程序编写

在测试代码中,有大量的重复代码。所以我们第一反应就是想给它抽取出共性的部分,

但是SqlSession、SqlSessionFactory、SqlSessionFactoryBuilder有着各自的生命周期,

因为这些生命周期的不同,抽取时要有针对性的处理。

sqlSession使用范围:
SqlSessionFactoryBuilder

它的作用只是通过配置文件创建SqlSessionFactory,所以只要创建出SqlSessionFactory,它就可以销毁了。

所以说,它的生命周期是在方法之内。

 SqlSessionFactory

它的作用是创建SqlSession的工厂,工厂一旦创建,除非应用停掉,不要销毁。

所以说它的生命周期是在应用范围内。这里可以通过单例模式来管理它。

在mybatis整合spring之后,最好的处理方式是把SqlSessionFactory交由spring来做单例管理。

 SqlSession

SqlSession是一个面向用户(程序员)的接口,它的默认实现是DefaultSqlSession。

Mybatis是通过SqlSession来操作数据库的。SqlSession中不仅包含要处理的SQL信息,还包括一些数据信息,

所以说它是线程不安全的,因此它最佳的生命周期范围是在方法体之内。

UserDao:

 

package com.hcx.mybatis.dao;

import java.util.List;

import org.apache.ibatis.session.SqlSession;

import com.hcx.mybatis.po.User;

/**
 *  
 * <p>
 * Title: UserDao
 */
public interface UserDao {
	// 1、 根据用户ID查询用户信息
	public User findUserById(int id) throws Exception;

	// 2、 根据用户名称模糊查询用户列表
	public List<User> findUsersByName(String name) throws Exception;

	// 3、 添加用户
	public void insertUser(User user) throws Exception;

}
 

 

UserDaoImpl:

需要向dao实现类中注入SqlSessionFactory,在方法体内通过SqlSessionFactory创建SqlSession

要注意SqlSession和SqlSessionFactory的生命周期。

 

package com.hcx.mybatis.dao;

import java.util.List;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import com.hcx.mybatis.po.User;

/**
 * Title: UserDaoImpl
 */
public class UserDaoImpl implements UserDao {

	// 依赖注入
	private SqlSessionFactory sqlSessionFactory;
        //使用构造方法来初始化SqlSessionFactory
	public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
		this.sqlSessionFactory = sqlSessionFactory;
	}

	@Override
	public User findUserById(int id) throws Exception {
		// 通过工厂在方法内部获取sqlsession,这样可以避免线程安全问题
		SqlSession sqlSession = sqlSessionFactory.openSession();
		// 调用SqlSession的增删改查方法
		// 第一个参数:表示statement的唯一标示
		User user = sqlSession.selectOne("test.findUserById", id);
		System.out.println(user);
		// 关闭资源
		sqlSession.close();
		return user;
	}

	@Override
	public List<User> findUsersByName(String name) {
		// 创建SqlSession
		SqlSession sqlSession = sqlSessionFactory.openSession();

		// 调用SqlSession的增删改查方法
		// 第一个参数:表示statement的唯一标示
		List<User> list = sqlSession.selectOne("test.findUsersByName", name);
		System.out.println(list);
		// 关闭资源
		sqlSession.close();
		return list;
	}

	@Override
	public void insertUser(User user) {
		// 创建SqlSession
		SqlSession sqlSession = sqlSessionFactory.openSession();

		// 调用SqlSession的增删改查方法
		// 第一个参数:表示statement的唯一标示
		sqlSession.insert("test.insertUser", user);

		System.out.println(user.getId());
		// 提交事务
		sqlSession.commit();
		// 关闭资源
		sqlSession.close();
	}

}
 

 

UserDaoTest:


public class UserDaoTest {

	//声明全局的SqlSessionFactory
	private SqlSessionFactory sqlSessionFactory;
	
	@Before
	public void setUp() throws Exception {
		// 1、读取配置文件
		String resource = "SqlMapConfig.xml";
		InputStream inputStream = Resources.getResourceAsStream(resource);
		// 2、根据配置文件创建SqlSessionFactory
		sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
	}

	@Test
	public void testFindUserById() {
		//构造UserDao对象
		UserDao userDao = new UserDaoImpl(sqlSessionFactory);
		//调用UserDao对象的方法
		User user = userDao.findUserById(1);
		
		System.out.println(user);
	}

	@Test
	public void testFindUsersByName() {
		//构造UserDao对象
		UserDao userDao = new UserDaoImpl(sqlSessionFactory);
		//调用UserDao对象的方法
		List<User> list = userDao.findUsersByName("小明");
		
		System.out.println(list);
	}

	@Test
	public void testInsertUser() {
		//构造UserDao对象
		UserDao userDao = new UserDaoImpl(sqlSessionFactory);
		//构造User对象
		User user = new User();
		user.setUsername("东哥3");
		user.setAddress("清河宝盛西里3");
		
		//调用UserDao对象的方法
		userDao.insertUser(user);
		
		System.out.println(user.getId());
	}

}
 

 

4、问题总结

原始dao开发存在一些问题:

存在一定量的模板代码。比如:通过SqlSessionFactory创建SqlSession;调用SqlSession的方法操作数据库;关闭Sqlsession。

存在一些硬编码。调用SqlSession的方法操作数据库时,需要指定statement的id,这里存在了硬编码。

 

二、Mapper代理开发方式

Mapper代理的开发方式,程序员只需要编写mapper接口(相当于dao接口)即可。Mybatis会自动的为mapper接口生成动态代理实现类。

不过要实现mapper代理的开发方式,需要遵循一些开发规范。

1、开发规范

1、  mapper接口的全限定名要和mapper映射文件的namespace的值相同。

2、  mapper接口的方法名称要和mapper映射文件中的statement的id相同;

3、  mapper接口的方法参数只能有一个,且类型要和mapper映射文件中statement的parameterType的值保持一致。

4、  mapper接口的返回值类型要和mapper映射文件中statement的resultType值或resultMap中的type值保持一致;

 

通过规范式的开发mapper接口,可以解决原始dao开发当中存在的问题:

1、  模板代码已经去掉;

2、  剩下去不掉的操作数据库的代码,其实就是一行代码。这行代码中硬编码的部分,通过第一和第二个规范就可以解决。

 

2、编程步骤

1、  根据需求创建po类

2、  编写全局配置文件

3、  根据需求编写映射文件

4、  加载映射文件

5、  编写mapper接口

6、  编写测试代码

 

3、程序编写

(1)编写mapper映射文件

重新定义mapper映射文件UserMapper.xml(内容同Users.xml,除了namespace的值),放到新创建的目录mapper下。

UserMapper.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">
<!-- namespace:此时用mapper代理方式,它的值必须等于对应mapper接口的全限定名  -->
<mapper namespace="cn.hcx.mybatis.mapper.UserMapper">

	<!-- 根据用户ID,查询用户信息 -->
	<!-- 
		[id]:statement的id,要求在命名空间内唯一  
		[parameterType]:入参的java类型,可是是简单类型、POJO、HashMap
		[resultType]:查询出的单条结果集对应的java类型
		[#{}]: 表示一个占位符?
		[#{id}]:表示该占位符待接收参数的名称为id。注意:如果参数为简单类型时,#{}里面的参数名称可以是任意定义
	 -->
	<select id="findUserById" parameterType="int" resultType="cn.hcx.mybatis.po.User">
		SELECT * FROM USER WHERE id = #{id}
	</select>
	
	
	<!-- 根据用户名称模糊查询用户信息列表 -->
	<!-- 
		[${}]:表示拼接SQL字符串,即不加解释的原样输出
	 	[${value}]:表示要拼接的是简单类型参数。
		 注意:
		1、如果参数为简单类型时,${}里面的参数名称必须为value 
		2、${}会引起SQL注入,一般情况下不推荐使用。但是有些场景必须使用${},比如order by ${colname}
	-->
	<select id="findUsersByName" parameterType="java.lang.String" resultType="cn.hcx.mybatis.po.User">
		SELECT * FROM USER WHERE username LIKE '%${value}%'
	</select>
	
	<!-- 添加用户之自增主键返回(selectKey方式) -->
	<!-- 
		[selectKey标签]:通过select查询来生成主键
		[keyProperty]:指定存放生成主键的属性
		[resultType]:生成主键所对应的Java类型
		[order]:指定该查询主键SQL语句的执行顺序,相对于insert语句,此时选用AFTER
		[last_insert_id]:MySQL的函数,要配合insert语句一起使用
	 -->
	<insert id="insertUser" parameterType="cn.hcx.mybatis.po.User">
		<selectKey keyProperty="id" resultType="int" order="AFTER">
			SELECT LAST_INSERT_ID()
		</selectKey>
		INSERT INTO USER(username,sex,birthday,address) VALUES (#{username},#{sex},#{birthday},#{address})
	</insert>
	
</mapper>
 

(2)加载mapper映射文件

在SqlMapConfig.xml文件中:
<!-- 加载mapper -->
<mappers>
	<mapper resource="sqlmap/User.xml"/>
	<mapper resource="mapper/UserMapper.xml"/>
</mappers>

(3)编写mapper接口
内容与UserDao接口一样
public interface UserMapper {
	//根据用户ID来查询用户信息
	public User findUserById(int id);
	//根据用户名称来模糊查询用户信息列表
	public List<User> findUsersByName(String username);
	//添加用户
	public void insertUser(User user);
}

(4)编写测试代码
public class UserMapperTest {

	// 声明全局的SqlSessionFactory
	private SqlSessionFactory sqlSessionFactory;

	@Before
	public void setUp() throws Exception {
		// 1、读取配置文件
		String resource = "SqlMapConfig.xml";
		InputStream inputStream = Resources.getResourceAsStream(resource);
		// 2、根据配置文件创建SqlSessionFactory
		sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
	}

	@Test
	public void testFindUserById() {
		// 创建SqlSession
		SqlSession sqlSession = sqlSessionFactory.openSession();
		// 通过SqlSession,获取mapper接口的动态代理对象
		UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
		// 调用mapper对象的方法
		User user = userMapper.findUserById(1);

		System.out.println(user);
		// 关闭SqlSession
		sqlSession.close();

	}

	@Test
	public void testFindUsersByName() {
		// 创建SqlSession
		SqlSession sqlSession = sqlSessionFactory.openSession();
		// 通过SqlSession,获取mapper接口的动态代理对象
		UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
		// 调用mapper对象的方法
		List<User> list = userMapper.findUsersByName("小明");

		System.out.println(list);
		// 关闭SqlSession
		sqlSession.close();
	}

	@Test
	public void testInsertUser() {
		// 创建SqlSession
		SqlSession sqlSession = sqlSessionFactory.openSession();
		// 通过SqlSession,获取mapper接口的动态代理对象
		UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
		
		//构造User对象
		User user = new User();
		user.setUsername("东哥4");
		user.setAddress("清河宝盛西里4");
		
		// 调用mapper对象的方法
		userMapper.insertUser(user);

		System.out.println(user.getId());
		
		//执行SqlSession的commit操作
		sqlSession.commit();
		// 关闭SqlSession
		sqlSession.close();
	}

}

 
 
 
 
  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Mybatis-Plus 是 Mybatis 的增强工具,在 Mybatis 的基础上,提供了更加便捷的操作方式和更加强大的功能。使用 Mybatis-Plus 替换 DAO 层可以极大地提高开发效率和代码质量。 以下是使用 Mybatis-Plus 替换 DAO 层的步骤: 1. 添加依赖 在 pom.xml 文件中添加 Mybatis-Plus 的依赖: ```xml <!-- Mybatis-Plus --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.0</version> </dependency> ``` 2. 配置 Mybatis-Plus 在 application.yml 文件中配置 Mybatis-Plus: ```yaml mybatis-plus: # mapper 文件位置 mapper-locations: classpath:/mapper/**/*.xml # 实体类扫描路径 typeAliasesPackage: com.example.entity ``` 3. 创建实体类 使用 Mybatis-Plus 需要创建实体类,并且实体类需要继承 BaseMapper 接口。例如: ```java public interface UserMapper extends BaseMapper<User> { } ``` 4. 使用 Mybatis-Plus 进行 CRUD 操作 使用 Mybatis-Plus 进行 CRUD 操作非常简单,只需要在 Service 层中调用相应的方法即可。例如: ```java @Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Override public User getUserById(Long id) { return userMapper.selectById(id); } @Override public List<User> getUserList() { return userMapper.selectList(null); } @Override public int addUser(User user) { return userMapper.insert(user); } @Override public int updateUser(User user) { return userMapper.updateById(user); } @Override public int deleteUser(Long id) { return userMapper.deleteById(id); } } ``` 以上就是使用 Mybatis-Plus 替换 DAO 层的步骤,使用 Mybatis-Plus 可以极大地简化 DAO 层的开发,提高代码质量和开发效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值