1 SqlSession的介绍

  SqlSession中封装了对数据库的操作,比如:更新、删除、查询等。通过SqlSessionFactory创建SqlSession,而SqlSessionFactory是由SqlSessionFactoryBuilder来创建的。

1.1 SqlSessionFactoryBuilder

SqlSessionFactoryBuilder的作用是创建SqlSessionFacoty,SqlSessionFacoty创建了之后就不需要SqlSessionFactoryBuilder了,由于SqlSession是通过SqlSessionFactory生产,所以一般是将SqlSessionFactoryBuilder当成一个工具类使用,需要创建sqlSessionFactory时就new一个 SqlSessionFactoryBuilder,和Spring整合后由Spring以单例方式管理sqlSessionFactory。

1.2 SqlSessionFactory

SqlSession是一个面向用户的接口, sqlSession中定义了数据库操作,默认使用DefaultSqlSession实现类。

2 MaBatis对Dao层的开发方式

2.1 不使用Mapper动态代理开发

编写dao层接口

1
2
3
4
public interface UserDao {
//根据id查询用户
public User getUserById(Integer id);
}

编写dao层接口实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class UserDaoImpl implements UserDao {
//sqlSession 工厂
private SqlSessionFactory ssf;
//通过构造器给ssf赋值
public UserDaoImpl(SqlSessionFactory ssf) {
super();
this.ssf = ssf;
}
@Override
public User getUserById(Integer id) {
//生产一个sqlSession
SqlSession session = ssf.openSession();
User user session.selectOne("UserMapper.selectUserById",id);
session.close();
return user;
}
}

编写测试方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class UserDaoTest {
//sqlSession 工厂
private static SqlSessionFactory ssf;
static {
String resource = "sqlMapConfig.xml";
InputStream in;
try {
in = Resources.getResourceAsStream(resource);
SqlSessionFactoryBuilder ssfb = new SqlSessionFactoryBuilder();
ssf = ssfb.build(in);
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void DaoTest() {
UserDao dao = new UserDaoImpl(ssf);
User user = dao.getUserById(1);
System.out.println(user);
}
}

  不使用Mapper动态代理开发可以从代码中看到一些问题,每次我们调用SqlSession都要完成打开session、调用session完成与数据库的交互、关闭session,这三步,这些都是重复的代码。

2.2 使用Mapper动态代理开发

首先想使用Mapper动态代理开发必须遵循四大原则加一个注意:

  • 接口方法名需要与mapper.xml的要调用的sql语句的id一致
  • 接口的形参类型需要与mapper.xml中的parameterType一致
  • 接口的返回值需要与mapper.xml中的resultType一致
  • mapper.xml中的namespace要与接口的全包名一致
    注意:mapper动态代理开发中,根据返回值类型自动选择方法

UserMapper接口(mybatis提出mapper接口,相当于dao接口,mapper接口的命名方式建议为表名加Mapper)

1
2
3
4
public interface UserMapper {
//通过id查询一个用户
public User selectUserById(Integer id);
}

UserMapper映射文件(mapper映射文件的命名方式建议表名加Mapper.xml,namespace指定为mapper接口的全限定名)

1
2
3
4
5
6
7
<!-- mapper.xml中的namespace要与接口的全包名一致 -->
<mapper namespace="com.xiezhenyu.mapper.UserMapper">
<!-- 查找用户 -->
<select id="selectUserById" parameterType="Integer" resultType="user">
select * from user where u_id = #{id}
</select>
</mapper>

将mapper.xml在SqlMapConfing.xml中进行注册

1
2
3
<mappers>
<package name="com.xiezhenyu.mapper"/>
</mappers>

编写测试方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Test
public void Test1() throws IOException {
String resource = "sqlMapConfig.xml";
//读取配置文件
InputStream in = Resources.getResourceAsStream(resource);
//需要sqlSessionFactoryBulider
SqlSessionFactoryBuilder ssfb = new SqlSessionFactoryBuilder();
//创建sqlSessionFactory
SqlSessionFactory ssf = ssfb.build(in);
//生产一个sqlSession
SqlSession session = ssf.openSession();
UserMapper mapper = session.getMapper(UserMapper.class);
User user = mapper.selectUserById(1);
System.out.println(user);
}

结果:

1
User [u_id=1, u_username=老王, u_password=123, u_sex=1, u_createTime=null, u_cid=1]

总结:使用Mapper代理进行开发
  优点:可以使我们只需要关注UserMapper.java接口中的方法,它的实现类由Mapper自动为我们生成,带来了很大的方便。
  缺点:如果UserMapper.java接口中的方法调用的statement中返回是多条记录,而mapper.java方法的返回值为JavaBean对象,此时代理对象通过selectOne调用,但由于返回的是多条记录所以会报错。