一、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); } }