Mybatis第六篇【配置文件和映射文件再解读、占位符、主键生成与获取、Mapper代理】
配置文件和映射文件再解读
映射文件
在mapper.xml文件中配置很多的sql语句,执行每个sql语句时,封装为MappedStatement对象,mapper.xml以statement为单位管理sql语句
Statement的实际位置就等于namespace+StatementId
配置文件
别名
typeAliases别名:
自定义别名:
<!-- 定义 别名 -->
<typeAliases>
<!--
单个别名的定义
alias:别名,type:别名映射的类型 -->
<!-- <typeAlias type="cn.itcast.mybatis.po.User" alias="user"/> -->
<!-- 批量别名定义
指定包路径,自动扫描包下边的pojo,定义别名,别名默认为类名(首字母小写或大写)
-->
<package name="cn.itcast.mybatis.po"/>
</typeAliases>
Mapper加载
<mappers>
<!-- 通过resource引用mapper的映射文件 -->
<mapper resource="sqlmap/User.xml" />
<!-- <mapper resource="mapper/UserMapper.xml" /> -->
<!-- 通过class引用mapper接口
class:配置mapper接口全限定名
要求:需要mapper.xml和mapper.java同名并且在一个目录 中
-->
<!-- <mapper class="cn.itcast.mybatis.mapper.UserMapper"/> -->
<!-- 批量mapper配置
通过package进行自动扫描包下边的mapper接口,
要求:需要mapper.xml和mapper.java同名并且在一个目录 中
-->
<package name="cn.itcast.mybatis.mapper"/>
</mappers>
Mybatis解决JDBC编程的问题
1、数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。
- 解决:在SqlMapConfig.xml中配置数据链接池,使用连接池管理数据库链接。
2、Sql语句写在代码中造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。
- 解决:将Sql语句配置在XXXXmapper.xml文件中与java代码分离。
3、向sql语句传参数麻烦,因为sql语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应。
- 解决:Mybatis自动将java对象映射至sql语句,通过statement中的parameterType定义输入参数的类型。
4、对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成pojo对象解析比较方便。
- 解决:Mybatis自动将sql执行结果映射至java对象,通过statement中的resultType定义输出结果的类型。
占位符
在Mybatis中,有两种占位符
- #{}解析传递进来的参数数据
- ${}对传递进来的参数原样拼接在SQL中
主键生成策略
如果我们在Hibernate中,当我们插入数据的时候,我们是可以选择是UUID策略的…
那么在Mybatis是怎么做的呢??
UUID
<!-- mysql的uuid生成主键 -->
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
<selectKey keyProperty="id" order="BEFORE" resultType="string">
select uuid()
</selectKey>
INSERT INTO USER(id,username,birthday,sex,address) VALUES(#{id},#{username},#{birthday},#{sex},#{address})
</insert>
主键返回
如果我们一般插入数据的话,如果我们想要知道刚刚插入的数据的主键是多少,我们可以通过以下的方式来获取
需求:
- user对象插入到数据库后,新记录的主键要通过user对象返回,通过user获取主键值。
解决思路:
- 通过LAST_INSERT_ID()获取刚插入记录的自增主键值,在insert语句执行后,执行select LAST_INSERT_ID()就可以获取自增主键。
mysql:
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
<selectKey keyProperty="id" order="AFTER" resultType="int">
select LAST_INSERT_ID()
</selectKey>
INSERT INTO USER(username,birthday,sex,address) VALUES(#{username},#{birthday},#{sex},#{address})
</insert>
oracle:
实现思路:
- 先查询序列得到主键,将主键设置到user对象中,将user对象插入数据库。
<!-- oracle
在执行insert之前执行select 序列.nextval() from dual取出序列最大值,将值设置到user对象 的id属性
-->
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
<selectKey keyProperty="id" order="BEFORE" resultType="int">
select 序列.nextval() from dual
</selectKey>
INSERT INTO USER(id,username,birthday,sex,address) VALUES(#{id},#{username},#{birthday},#{sex},#{address})
</insert>
Mapper代理方式
Mapper代理方式的意思就是:程序员只需要写dao接口,dao接口实现对象由mybatis自动生成代理对象。
经过我们上面的几篇博文,我们可以发现我们的DaoImpl是十分重复的…
1 dao的实现类中存在重复代码,整个mybatis操作的过程代码模板重复(先创建sqlsession、调用sqlsession的方法、关闭sqlsession)
2、dao的实现 类中存在硬编码,调用sqlsession方法时将statement的id硬编码。
以前的重复代码和硬编码如下:
public class StudentDao {
public void add(Student student) throws Exception {
//得到连接对象
SqlSession sqlSession = MybatisUtil.getSqlSession();
try{
//映射文件的命名空间.SQL片段的ID,就可以调用对应的映射文件中的SQL
sqlSession.insert("StudentID.add", student);
sqlSession.commit();
}catch(Exception e){
e.printStackTrace();
sqlSession.rollback();
throw e;
}finally{
MybatisUtil.closeSqlSession();
}
}
public static void main(String[] args) throws Exception {
StudentDao studentDao = new StudentDao();
Student student = new Student(3, "zhong3", 10000D);
studentDao.add(student);
}
}
Mapper开发规范
想要Mybatis帮我们自动生成Mapper代理的话,我们需要遵循以下的规范:
1、mapper.xml中namespace指定为mapper接口的全限定名
- 此步骤目的:通过mapper.xml和mapper.java进行关联。
2、mapper.xml中statement的id就是mapper.java中方法名
3、mapper.xml中statement的parameterType和mapper.java中方法输入参数类型一致
4、mapper.xml中statement的resultType和mapper.java中方法返回值类型一致.
再次说明:statement就是我们在mapper.xml文件中写sql指定的id
Mapper代理返回值问题
mapper接口方法返回值:
- 如果是返回的单个对象,返回值类型是pojo类型,生成的代理对象内部通过selectOne获取记录
- 如果返回值类型是集合对象,生成的代理对象内部通过selectList获取记录。