使用
MyBatis
开发
Dao
,通常有两个方法,即原始
Dao
开发方法和
Mapper
动态代理开发方法。
7.1. SqlSession
的使用范围
SqlSession
中封装了对数据库的操作,如:查询、插入、更新、删除等。
SqlSession
通过SqlSessionFactory
创建。
SqlSessionFactory
是通过SqlSessionFactoryBuilder
进行创建。
7.1.1. SqlSessionFactoryBuilder
SqlSessionFactoryBuilder
用于创建SqlSessionFacoty
,SqlSessionFacoty
一旦创建完成就不需要SqlSessionFactoryBuilder
了,因为SqlSession
是通过SqlSessionFactory
创建的。所以可以将SqlSessionFactoryBuilder
当成一个工具类使用,最佳使用范围是方法范围即方法体内局部变量。
7.1.2. SqlSessionFactory
SqlSessionFactory
是一个接口,接口中定义了openSession
的不同重载方法,SqlSessionFactory
的最佳使用范围是整个应用运行期间,一旦创建后可以重复使用,通常以单例模式管理SqlSessionFactory
。
7.1.3. SqlSession
SqlSession
是一个面向用户的接口,sqlSession
中定义了数据库操作方法。
每个线程都应该有它自己的
SqlSession
实例。
SqlSession
的实例不能共享使用,它也是线程不安全的。因此最佳的范围是请求或方法范围。绝对不能将
SqlSession
实例的引用放在一个类的静态字段或实例字段中。
打开一个 SqlSession
;使用完毕就要关闭它。通常把这个关闭操作放到 finally
块中以确保每次都能执行关闭。如下:
SqlSession
session
=
sqlSessionFactory
.openSession();
try
{
// do work
}
finally
{
session
.close();
}
7.2.
原始
Dao
开发方式
原始Dao
开发方法需要程序员编写Dao
接口和Dao
实现类。
7.2.1.
映射文件
编写映射文件如下:(也可以使用入门程序完成的映射文件)
<?
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
=
"test"
>
<!-- 根据id查询用户 -->
<
select
id
=
"queryUserById"
parameterType
=
"int"
resultType
=
"cn.itcast.mybatis.pojo.User"
>
select * from user where id = #{id}
</
select
>
<!-- 根据username模糊查询用户 -->
<
select
id
=
"queryUserByUsername"
parameterType
=
"string"
resultType
=
"cn.itcast.mybatis.pojo.User"
>
select * from user where username like '%${value}%'
</
select
>
<!-- 保存用户 -->
<
insert
id
=
"saveUser"
parameterType
=
"cn.itcast.mybatis.pojo.User"
>
<
selectKey
keyProperty
=
"id"
keyColumn
=
"id"
order
=
"AFTER"
resultType
=
"int"
>
SELECT LAST_INSERT_ID()
</
selectKey
>
insert into user(username,birthday,sex,address)
values(#{username},#{birthday},#{sex},#{address})
</
insert
>
</
mapper
>
7.2.2. Dao
接口
先进行DAO
的接口开发,编码如下:
public
interface
UserDao {
/**
* 根据id查询用户
*
@param
id
*
@return
*/
User queryUserById(
int
id
);
/**
* 根据用户名模糊查询用户
*
@param
username
*
@return
*/
List<User> queryUserByUsername(String
username
);
/**
* 保存用户
*
@param
user
*/
void
saveUser(User
user
);
}
7.2.3. Dao
实现类
编写的Dao
实现类如下
public
class
UserDaoImpl
implements
UserDao {
private
SqlSessionFactory
sqlSessionFactory
;
public
UserDaoImpl(SqlSessionFactory
sqlSessionFactory
) {
super
();
this
.
sqlSessionFactory
=
sqlSessionFactory
;
}
@Override
public
User queryUserById(
int
id
) {
// 创建SqlSession
SqlSession
sqlSession
=
this
.
sqlSessionFactory
.openSession();
// 执行查询逻辑
User
user
=
sqlSession
.selectOne(
"queryUserById"
,
id
);
// 释放资源
sqlSession
.close();
return
user
;
}
@Override
public
List<User> queryUserByUsername(String
username
) {
// 创建SqlSession
SqlSession
sqlSession
=
this
.
sqlSessionFactory
.openSession();
// 执行查询逻辑
List<User>
list
=
sqlSession
.selectList(
"queryUserByUsername"
,
username
);
// 释放资源
sqlSession
.close();
return
list
;
}
@Override
public
void
saveUser(User
user
) {
// 创建SqlSession
SqlSession
sqlSession
=
this
.
sqlSessionFactory
.openSession();
// 执行保存逻辑
sqlSession
.insert(
"saveUser"
,
user
);
// 提交事务
sqlSession
.commit();
// 释放资源
sqlSession
.close();
}
}
1.1.4. Dao
测试
创建一个JUnit
的测试类,对UserDao
进行测试,测试代码如下:
public
class
UserDaoTest {
private
SqlSessionFactory
sqlSessionFactory
;
@Before
public
void
init()
throws
Exception {
// 创建SqlSessionFactoryBuilder
SqlSessionFactoryBuilder
sqlSessionFactoryBuilder
=
new
SqlSessionFactoryBuilder();
// 加载SqlMapConfig.xml配置文件
InputStream
inputStream
= Resources.
getResourceAsStream
(
"SqlMapConfig.xml"
);
// 创建SqlsessionFactory
this
.
sqlSessionFactory
=
sqlSessionFactoryBuilder
.build(
inputStream
);
}
@Test
public
void
testQueryUserById() {
// 创建DAO
UserDao
userDao
=
new
UserDaoImpl(
this
.
sqlSessionFactory
);
// 执行查询
User
user
=
userDao
.queryUserById(1);
System.
out
.println(
user
);
}
@Test
public
void
testQueryUserByUsername() {
// 创建DAO
UserDao
userDao
=
new
UserDaoImpl(
this
.
sqlSessionFactory
);
// 执行查询
List<User>
list
=
userDao
.queryUserByUsername(
"张"
);
for
(User
user
:
list
) {
System.
out
.println(
user
);
}
}
@Test
public
void
testSaveUser() {
// 创建DAO
UserDao
userDao
=
new
UserDaoImpl(
this
.
sqlSessionFactory
);
// 创建保存对象
User
user
=
new
User();
user
.setUsername(
"刘备"
);
user
.setBirthday(
new
Date());
user
.setSex(
"1"
);
user
.setAddress(
"蜀国"
);
// 执行保存
userDao
.saveUser(
user
);
System.
out
.println(
user
);
}
}
总结:
问题
原始Dao
开发中存在以下问题:
Dao
方法体存在重复代码:通过SqlSessionFactory
创建SqlSession
,调用SqlSession
的数据库操作方法
调用
sqlSession
的数据库操作方法需要指定
statement
的
id
,这里存在硬编码,不得于开发维护