MyBatis框架学习(三)-Mapper代理开发

前言:上一节我们学习了MyBatis的简单实现CRUD,在这个过程中我们用了原始的Dao的方法开发,在这个过程中我们发现存在一些弊端,如有很多重复的代码,sqlSession的操作,statement中id的硬编码给将来维护带来不便等等,这也是很多程序员苦恼的,因此推荐Mapper代理开发,简单高效,毕竟学习的过程总是先苦后甜.下面我们来一起研究Mapper代理开发.

一、基于Mapper的代理开发方式

在使用MyBatis开发Dao是,通常有两种方法,即原始Dao方法,和基于Mapper接口的方法,MyBatis在进行Dao开发时,一般会涉及到三姐妹,分别是SqlSessionFactoryBuilder、SqlSessionFactiory、SqlSession。
我们都知道SqlSession中封装了对数据库的操作,如增删改查,通过SqlSessionFactory创建SqlSession,而SqlSessionFactory是由SqlSessionFactoryBuilder创建的.

1. SqlSessionFactoryBuilder

SqlSessionFactoryBuilder用于创建SqlSessionFacoty,SqlSessionFacoty一旦创建完成就不需要SqlSessionFactoryBuilder了,因为SqlSession是通过SqlSessionFactory生产,所以可以将SqlSessionFactoryBuilder当成一个工具类使用,最佳使用范围是方法范围即方法体内局部变量。

2.SqlSessionFactory

SqlSessionFactory是一个接口,接口中定义了openSession的不同重载方法,SqlSessionFactory的最佳使用范围是整个应用运行期间,一旦创建后可以重复使用,通常以单例模式管理SqlSessionFactory。

3.SqlSession

SqlSession是一个面向用户的接口, sqlSession中定义了数据库操作,默认使用DefaultSqlSession实现类。
SqlSession中提供了很多操作数据库的方法:如:selectOne(返回单个对象)、selectList(返回单个或多个对象),SqlSession是线程不安全的,在SqlSesion实现类中除了有接口中的方法(操作数据库的方法)还有数据域属性,SqlSession最佳应用场合在方法体内,定义成局部变量使用,绝对不能将SqlSession实例的引用放在一个类的静态字段或实例字段中。今天的博文中,小编将着重介绍小伙伴们介绍mybatis中开发dao的两种方法,原始dao的开发方式和mapper代理开发。
mybatis 中 dao 的开发方法,分别是原始 dao 的开发和 mapper 代理开发,原始Dao开发和Mapper动态代理开发,这两种各有优点。原始Dao开发:程序员要写Dao和Dao实现,需要些较多的代码,但是比较好理解。Mapper动态代理:程序员只需要写Mapper接口,然后按照规范进行配置,MyBatis就会自动实现类似Dao实现,减少模板方法。mybatis官方推荐使用mapper代理方法开发mapper接口,程序员不用编写mapper接口实现类,使用mapper代理方法时,输入参数可以使用pojo包装对象或map对象,保证dao的通用性。

二、Mapper代理开发的实列

1. Mapper代理开发的一些规则

*xxxmapper.xml中的namespace等于mapper接口地址
*xxxmapper.java接口中的方法 xxxmapper.xml中的statement的id一致
*xxxmapper.java接口中的方法输入参数和xxxmapper.xml中statement的parameterType指定类型一致
*xxxmapper.java接口中的方法的返回值类型和xxxmapper.xml中resultType指定的类型一致

2.MyBatis的开发过程
☐ 编写MyBatis的配置文件MyBatis-config.xml
☐ 编写MyBatis的映射文件xxxmapper.xml(这里主要是statement和sql语句)
☐ 编写MyBatis的接口方法xxxmapper.java(注意这里方法名与映射文件中的
statement一致)
☐ 通过SqlSessionFactory获取SqlSession
☐ 通过SqlSesson操作数据库(执行CRUD需要调用的SqlSession.commit()
☐ SqlSession使用完关闭数据库

3.首先创建一个user数据库

use mybatis;

create table user(
	id int null auto_increment,
	name varchar(32) not null,
	password varchar(32) not null,
	age int not null,
	create_time datetime null,
	primary key(id)
);
4.加入日志包,创建一个mybatis-config.xml的配置文件
<?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>
	<!-- 开启驼峰命名法规则,create_time 就等于createTime  -->
	<settings>
		<setting name="mapUnderscoreToCamelCase" value="true"/>
	</settings>
	<!-- 默认引用那个数据库环境 -->
	<environments default="development">
		<environment id="development">
			<!-- 事务管理方式 -->
			<transactionManager type="JDBC" />
			<!-- 数据库连接四要素 -->
			<dataSource type="POOLED">
				<property name="driver" value="com.mysql.jdbc.Driver" />
				<property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis" />
				<property name="username" value="root" />
				<property name="password" value="root" />
			</dataSource>
		</environment>
	</environments>
	<!-- SQL的映射文件 -->
	<mappers>
		<mapper resource="com/dqsy/mybatis/mapper/UserMapper.xml" />
	</mappers>
</configuration>
5.创建一个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">
<mapper namespace="com.dqsy.mybatis.mapper.UserMapper">
<!--  
	id:表示一个SQL句柄,相当于JDBC中的statement
	parametaerType:输入参数的类型,在SQL语句中,通过占位符#{}来接受参数
	resultType:SQL操作的返回结果类型
-->
  <!-- 单个查询 -->
  <select id="getUserById" parameterType="java.lang.Integer" 
  resultType="com.dqsy.mybatis.entity.User">
    select id,name,password,age,create_time from user where id=#{id}
  </select>
  <!-- 查询列表 -->
  <select id="getUserList" resultType="com.dqsy.mybatis.entity.User">
  	select id,name,password,age,create_time from user
  </select>
  <!-- 添加用户 注意在这传参是java里的参数 而不是数据库里的字段名-->
  <select id="addUser" parameterType="com.dqsy.mybatis.entity.User">
  	insert into user(name,password,age,create_time) values(#{name}, #{password} ,#{age}, #{createTime})
  </select>
  <!-- 删除用户 -->
  <select id="delUser" parameterType="java.lang.Integer">
  	delete from user where id = #{id}
  </select>
  <!-- 修改用户的数据 -->
  <select id="uptUser" parameterType="com.dqsy.mybatis.entity.User">
  	update user set name=#{name}, password=#{password}, age=#{age}, create_time=#{createTime} where id=#{id}
  </select>
</mapper>
6.同时在该包下创建一个与映射文件对应的UserMapper.java的接口
package com.dqsy.mybatis.mapper;

import java.util.List;

import com.dqsy.mybatis.entity.User;

public interface UserMapper {
	public User getUserById(int id);
	public List<User> getUserList();
	public void addUser(User user);
	public void delUser(int i);
	public void uptUser(User user);
}
7.创建一个User的实体类(并实现getset方法和tostring方法)
public class User {
	private int id;
	private String name;
	private String password;
	private int age;
	private Date createTime;
8.建立一个测试类MapperTest
package com.dqsy.mybatis.test;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;

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 org.junit.Before;
import org.junit.Test;

import com.dqsy.mybatis.entity.User;
import com.dqsy.mybatis.mapper.UserMapper;

public class MapperTest {
	private SqlSessionFactory sqlSessionFactory;
	@Before
	public void init() throws IOException{
		String configFile = "mybatis-config.xml";
		InputStream inputStream = Resources.getResourceAsStream(configFile);
		sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
	}
	@Test
	public void TestGetUserById(){
		SqlSession sqlSession = sqlSessionFactory.openSession();
		UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
		System.out.println(userMapper.getUserById(1));
		sqlSession.close();
	}
	//查询用户
	@Test
	public void TestGetUserList(){
		SqlSession sqlSession = sqlSessionFactory.openSession();
		UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
		List<User> users = userMapper.getUserList(); 
		for(User u: users){
			System.out.println(u);
		}
		sqlSession.close();
	}
	//添加用户
	@Test
	public void TestAddUser(){
		SqlSession sqlSession = sqlSessionFactory.openSession();
		UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
		User user = new User();
		user.setName("鲁金环");
		user.setPassword("123");
		user.setAge(23);
		user.setCreateTime(new Date());
		userMapper.addUser(user);	
		sqlSession.commit();
		sqlSession.close();
	}
	//删除用户
	@Test
	public void TestdelUser(){
		SqlSession sqlSession = sqlSessionFactory.openSession();
		UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
		userMapper.delUser(1);	
		sqlSession.commit();
		sqlSession.close();
	}
	//修改用户
	@Test
	public void TestuptUser(){
		SqlSession sqlSession = sqlSessionFactory.openSession();
		UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
		User user = new User();
		user.setId(2);
		user.setName("王巍");
		user.setPassword("123");
		user.setAge(23);
		user.setCreateTime(new Date());
		userMapper.uptUser(user);	
		sqlSession.commit();
		sqlSession.close();
	}
}
8.测试结果在这我就截一下数据库的图就行

在这注意下整个包的结构

三、总结(#{}和${}的区别)

#{}表示一个占位符号,#{}接收输入参数,类型可以是简单类型,pojo、hashmap。
如果接收简单类型,#{}中可以写成value或其它名称。
#{}接收pojo对象值,通过OGNL读取对象中的属性值,通过属性.属性.属性...的方式获取对象属性值。

${}表示一个拼接符号,会引用sql注入,所以不建议使用${}
${}接收输入参数,类型可以是简单类型,pojo、hashmap。
如果接收简单类型,${}中只能写成value。
${}接收pojo对象值,通过OGNL读取对象中的属性值,通过属性.属性.属性...的方式获取对象属性值。

selectOne和selectList
动态代理对象调用sqlSession.selectOne()和sqlSession.selectList()是根据mapper接口方法的返回值决定,如果返回list则调用selectList方 法,如果返回单个对象则调用selectOne方法。

namespace
mybatis官方推荐使用mapper代理方法开发mapper接口,程序员不用编写mapper接口实现类,使用mapper代理方法时,输入参数可以使用pojo包装对象或map对象,保证dao的通用性。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奋斗的小巍

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值