一、SqlSession 使用范围
SqlSessionFactoryBuilder
通过 SqlSessionFactoryBuilder 创建会话工厂 SqlSessionFactory
将 SqlSessionFactoryBuilder 当成一个工具类使用即可,不需要使用单例管理 SqlSessionFactoryBuilder 。
在需要创建 SqlSessionFactory 时候,只需要 new 一次 SqlSessionFactoryBuilder 即可
SqlSessionFactory
通过 SqlSessionFactory 创建 SqlSession,使用单例模式管理 sqlSessionFactory(工厂一旦创建,使用一个实例)。
将来 mybatis 和 spring 整合后,使用单例模式管理 sqlSessionFactory。
SqlSession
SqlSession 是面向用户(程序员)的接口。
SqlSession 是线程不安全的,在 SqlSession 实现类中除了有接口的方法(操作数据库方法),还有数据域属性。
SqlSession 最佳应用场合是在方法体内,定义成局部变量使用。
二、原始 dao 开发方法
(程序员需要写 dao 接口和 dao 实现类)
dao 接口:
public interface UserDao {
//根据id查询用户信息
public User findUserById(int id) throws Exception;
//根据用户名列查询用户列表
public List<User> findUserByName(String name) throws Exception;
//添加用户信息
public void insertUser(User user) throws Exception;
//删除用户信息
public void deleteUser(int id) throws Exception;
}
dao 实现类:
public class UserDaoImpl implements UserDao {
// 需要向dao实现类中注入SqlSessionFactory
// 这里通过构造方法注入
private SqlSessionFactory sqlSessionFactory;
public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
this.sqlSessionFactory = sqlSessionFactory;
}
@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 List<User> findUserByName(String name) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
List<User> list = sqlSession.selectList("test.findUserByName", name);
// 释放资源
sqlSession.close();
return list;
}
@Override
public void insertUser(User user) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
//执行插入操作
sqlSession.insert("test.insertUser", user);
// 提交事务
sqlSession.commit();
// 释放资源
sqlSession.close();
}
@Override
public void deleteUser(int id) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
//执行插入操作
sqlSession.delete("test.deleteUser", id);
// 提交事务
sqlSession.commit();
// 释放资源
sqlSession.close();
}
}
Junit 测试:
单独新建 test 文件夹,然后再要测试类文件上右键 新建 Junit Test Case。
public class UserDaoImplTest {
private SqlSessionFactory sqlSessionFactory;
// 此方法是在执行testFindUserById之前执行
@Before
public void setUp() throws Exception {
// 创建sqlSessionFactory
// mybatis配置文件
String resource = "SqlMapConfig.xml";
// 得到配置文件流
InputStream inputStream = Resources.getResourceAsStream(resource);
// 创建会话工厂,传入mybatis的配置文件信息
sqlSessionFactory = new SqlSessionFactoryBuilder()
.build(inputStream);
}
@Test
public void testFindUserById() throws Exception {
// 创建UserDao的对象
UserDao userDao = new UserDaoImpl(sqlSessionFactory);
// 调用UserDao的方法
User user = userDao.findUserById(1);
System.out.println(user);
}
}
原始 dao 开发问题
- dao 接口实现类方法中存在大量模板方法,设想能否将这些代码提取出来,大大减轻程序员的工作量。
- 调用 sqlsession 方法时将 statement 的 id 硬编码了
- 调用 sqlsession 方法时传入的变量,由于sqlsession方法使用泛型,即使变量类型传入错误,在编译阶段也不报错,不利于程序员开发。
三、mapper 代理方法
(程序员只需要 mapper 接口(相当 于 dao 接口))
开发规范:
1、在 第一节的 UserMapper.xml 中 namespace 只是任意定义字符串,而 UserMapper 代理方法 namespace 等于 mapper 接口地址。
即:
<mapper namespace="com.mapper.UserMapper">
2、UserMapper.java 接口中的方法名和 UserMapper.xml 中 statement 的 id 一致。
3、UserMapper.java 接口中的方法输入参数类型和 UserMapper.xml 中 statement 的 parameterType 指定的类型一致。
4、UserMapper.java 接口中的方法返回值类型和 UserMapper.xml 中 statement 的 resultType 指定的类型一致。
即代码可以直接写成:(不用再写 DaoImp 类)
<select id="findUserById" parameterType="int" resultType="com.po.User">
SELECT * FROM USER WHERE id=#{value}
</select>
//根据id查询用户信息
public User findUserById(int id) throws Exception;
mapper 代理用意:
以上开发规范主要是对下边的代码进行统一生成:
User user =sqlSession.selectOne("test.findUserById", id);
sqlSession.insert("test.insertUser",user);
。。。。
UserMapper 接口:
public interface UserMapper {
//根据id查询用户信息
public User findUserById(int id) throws Exception;
//根据用户名列查询用户列表
public List<User> findUserByName(String name) throws Exception;
//添加用户信息
public void insertUser(User user) throws Exception;
//删除用户信息
public void deleteUser(int id) throws Exception;
}
Test类
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
public class UserMapperTest {
private SqlSessionFactory sqlSessionFactory;
// 此方法是在执行testFindUserById之前执行
@Before
public void setUp() throws Exception {
// 创建sqlSessionFactory
// mybatis配置文件
String resource = "SqlMapConfig.xml";
// 得到配置文件流
InputStream inputStream = Resources.getResourceAsStream(resource);
// 创建会话工厂,传入mybatis的配置文件信息
sqlSessionFactory = new SqlSessionFactoryBuilder()
.build(inputStream);
}
@Test
public void testFindUserById() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
//创建UserMapper对象,mybatis自动生成mapper代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//调用userMapper的方法
User user = userMapper.findUserById(1);
System.out.println(user);
}
@Test
public void testFindUserByName() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
//创建UserMapper对象,mybatis自动生成mapper代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//调用userMapper的方法
List<User> list = userMapper.findUserByName("小明");
sqlSession.close();
System.out.println(list);
}
}