首先,SqlSession 使用范围:
我们在用mybatis访问数据库是使用SqlSession来操作数据的,在这之前,我们需要先创建SqlSessionFactory来创建,SqlSessionFactory是一个接口,使用它我们需要通SqlSessionFactoryBuilder来创建。
1. SqlSessionFactoryBuilder
通过SqlSessionFactoryBuilder创建会话工厂SqlSessionFactory,我们只需要将它当成一个工具类即可,不需要去使用单例管理。因为在创建SqlSessionFactory时,只new了一次。
2. SqlSessionFactory
通过SqlSessionFactory创建SqlSession,使用单例模式管理sqlSessionFactory(工厂一旦创建,使用一个实例)。
3. SqlSession
(1)SqlSession是一个面向用户(程序员)的接口。
(2)SqlSession中提供了很多操作数据库的方法:如:selectOne(返回单个对象)、selectList(返回单个或多个对象)。
(3)SqlSession是线程不安全的,因为在SqlSession实现类中除了有接口中的方法(操作数据库的方法)还有数据域属性。
(4)SqlSession最佳应用场合在方法体内,定义成局部变量使用。
原始dao开发方法:
原始dao开发方法,程序员需要编写dao接口和dao实现类,在dao接口的实现类中注入SqlsessionFactory,在方法体内通过SqlSessionFactory创建SqlSession
(1)dao接口:
与mapper映射中的id一一对应,声明出接口,那个简单地例子来说:
public interface UserDao {
//根据id查询用户信息
public User findUserById(int id) throws Exception;
//添加用户信息
public void insertUser(User user) throws Exception;
//删除用户信息
public void deleteUser(int id) throws Exception;
}
(2)dao接口的实现类:实现dao接口的方法,并将SqlsessionFactory注入:
public class UserDaoImpl implements UserDao{
//需要向dao实现类中注入SqlSessionFactory
private SqlSessionFactory sqlSessionFactory;
public UserDaoImpl(SqlSessionFactory sessionFactory) {
this.sqlSessionFactory = sessionFactory;
}
@Override
public User findUserById(int id) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = sqlSession.selectOne("test.findUserByID",id);
sqlSession.close();
return user;
}
@Override
public void insertUser(User user) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
//执行插入操作
sqlSession.selectOne("test.InsertUser",user);
//提交事务
sqlSession.commit();
//释放资源
sqlSession.close();
}
@Override
public void deleteUser(int id) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
//执行插入操作
sqlSession.selectOne("test.deleteUser",36);
sqlSession.commit();
sqlSession.close();
}
从上述可以看出在mybatis中存在的问题:
首先,在dao的实现方法中存在重复编码,每次都需要重新定义sqlsession.
其次,调用sqlsession的数据库操作方法存在硬编码,需要指定statement的id,这样不利于开发维护。
还有就是在调用sqlsession方法时传入的变量,由于sqlsession方法使用泛型,即使变量类型传入错误,在编译阶段也不报错,不利于程序员开发。
比如:
sqlSession.selectOne("test.deleteUser",36);
这块36传入参数的话就属于是泛型,这块接收的是object对象,所以你即使对象类型传入错误也不会报错。
mapper代理方法
针对上面出现的问题,我们可以用mapper代理的方法来返回进行处理。
mapper代理方法开发规范
1、在mapper.xml中namespace等于mapper接口地址
<mapper namespace="com.mapper.UserMapper">
2、mapper.java接口中的方法名和mapper.xml中statement的id一致
就是说在userMapper.java中的方法名应该和userMapper.xml中的statement id一致
<select id="findUserByID" parameterType="int" resultType="com.po.User">
//根据id查询用户信息
public User findUserByID(int id) throws Exception;
3、mapper.java接口中的方法输入参数类型和mapper.xml中statement的parameterType指定的类型一致。
4、mapper.java接口中的方法返回值类型和mapper.xml中statement的resultType指定的类型一致。
这两句话的比较好理解,就是要保证参数类型和返回结果类型一致。
比较完整的代码:
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.dy.mapper.UserMapper">
<select id="findUserByID" parameterType="int" resultType="com.dy.po.User">
select * from user
where id = #{id}
</select>
</mapper>
简单java对象:User
package com.dy.po;
import java.util.Date;
public class User {
private int id;
private String username;// 用户姓名
private String sex;// 性别
private Date birthday;// 生日
private String address;// 地址
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString(){
return "id : " + id + "userName : " + username ;
}
}
UserMapper.java接口:
package com.dy.mapper;
import com.dy.po.User;
public interface UserMapper {
//根据id查询用户信息
public User findUserByID(int id) throws Exception;
}
测试文件:
package com.dy.test;
import java.io.InputStream;
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.dy.mapper.UserMapper;
import com.dy.po.User;
public class UserMapperTest {
private SqlSessionFactory sessionFactory;
@Before
public void setUp() throws Exception{
//此方法实在testFindUserById之前执行的
//创建SqlSessionFactory
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void test() throws Exception {
SqlSession sqlSession = sessionFactory.openSession();
//创建userMapper对象,mybatis自动生成mapper代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//调用UserMapper的方法
User user = userMapper.findUserByID(1);
//代理对象内部调用selectOne查询数据库
System.out.println(user);
}
}
最重要的,在SqlMapConfig.xml中加载映射文件:
<!-- 加载映射文件 -->
<mapper resource = "com/dy/sqlMapper/userMapper.xml"/>
</mappers>
本文介绍了Mybatis中SqlSession的使用,包括SqlSessionFactoryBuilder和SqlSessionFactory的创建,以及SqlSession作为线程不安全接口的应用。讨论了原始DAO开发方法存在的问题,如重复编码和硬编码ID,然后详细阐述了Mapper代理方法的开发规范,如namespace与接口地址匹配,方法名与statement ID一致,以及参数和返回类型的对应,以提高开发效率和代码可维护性。
450

被折叠的 条评论
为什么被折叠?



