之前我们写的代码是基本使用方式,它也存在硬编码的问题,如下:
这里调用 selectList()
方法传递的参数是映射配置文件中的 namespace.id值。这样写也不便于后期的维护。如果使用 Mapper 代理方式(如下图)则不存在硬编码问题。
通过上面的描述可以看出 Mapper 代理方式的目的:
Mybatis 官网也是推荐使用 Mapper 代理的方式。
步骤详解:
①定义与SQL映射文件同名的Mapper接口,并且将Mapper接口和SQL映射文件放置在同一目录下。如下图:
不能直接把xml文件移动到一个文件夹中去,违背了maven配置文件与代码分离的思想。因为最后编译之后java文件夹与resources文件夹是会合并的,我们可以利用这一点在resources文件夹中。创造一个层级一模一样的文件夹把配置文件放进去。这样编译之后他们实际是在一个文件夹下面的。
注意:在这个过程中我们会发现在resources文件夹中不能创建package,只有Directory这个选项,我么利用它也可以达到相同的目的。但是在原来创建package我们使用.
来区别层级,而在Directory我们是使用/
来区别层级
②设置SQL映射文件的namespace属性为Mapper接口全限定名
全限定名:包名+类名(中间使用
.
分割的,不是/
,否则成路径了)
③在 Mapper 接口中定义方法,方法名就是SQL映射文件中sql语句的id,并保持参数类型和返回值类型一致
代码实现:
在 com.itheima.mapper
包下创建 UserMapper接口,代码如下:
public interface UserMapper {
List<User> selectAll();
}
在 resources
下创建 com/itheima/mapper
目录,并在该目录下创建 UserMapper.xml 映射配置文件
<mapper namespace="com.itheima.mapper.UserMapper">
<select id="selectAll" resultType="com.itheima.pojo.User">
select *
from tb_user;
select>
mapper>
在 com.itheima
包下创建 MybatisDemo2 测试类,代码如下:
/**
* Mybatis 代理开发
*/
public class MyBatisDemo2 {
public static void main(String[] args) throws IOException {
//1. 加载mybatis的核心配置文件,获取 SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2. 获取SqlSession对象,用它来执行sql
SqlSession sqlSession = sqlSessionFactory.openSession();
//3. 执行sql
//3.1 获取UserMapper接口的代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> users = userMapper.selectAll();
System.out.println(users);
//4. 释放资源
sqlSession.close();
}
}
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
这段代码,实际就是mybatis动态给我们创建了接口的实现类
调用SqlSession.getMapper()方法,mybatis自动给我们创建,省去我们自己去创建,我们只需要去关心接口里的方法,而不用管实现类。这也就是为什么称之为动态代理。
注意:
如果Mapper接口名称和SQL映射文件名称相同(不区分大小写),并在同一目录下,则可以使用包扫描的方式简化SQL映射文件的加载。也就是将核心配置文件的加载映射配置文件的配置修改为
<mappers>
<package name="com.itheima.mapper"/>
mappers>
不管有多少个映射文件,只需要一行代码就可以搞定。
这个地方有多种配置方法,文后有讲述
在核心配置文件的 environments
标签中其实是可以配置多个 environment
,使用 id
给每段环境起名,在 environments
中使用 default='环境id'
来指定使用哪儿段配置。我们一般就配置一个 environment
即可。
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///mybatis?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="1234"/>
dataSource>
environment>
<environment id="test">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///mybatis?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="1234"/>
dataSource>
environment>
environments>=
我们再来看两个配置项:
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源。有三种内建的数据源类型(也就是 type=“[UNPOOLED|POOLED|JNDI]”):
UNPOOLED
– 这个数据源的实现会每次请求时打开和关闭连接。虽然有点慢,但对那些数据库连接可用性要求不高的简单应用程序来说,是一个很好的选择。 性能表现则依赖于使用的数据库,对某些数据库来说,使用连接池并不重要,这个配置就很适合这种情形。POOLED
– 这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间。 这种处理方式很流行,能使并发 Web 应用快速响应请求。JNDI
– 这个数据源实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的数据源引用。在映射配置文件中的 resultType
属性需要配置数据封装的类型(类的全限定名)。而每次这样写是特别麻烦的,Mybatis 提供了 类型别名
(typeAliases) 可以简化这部分的书写。
类型别名(typeAliases)可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。
<typeAliases>
<typeAlias alias="Author" type="domain.blog.Author"/>
<typeAlias alias="Blog" type="domain.blog.Blog"/>
<typeAlias alias="Comment" type="domain.blog.Comment"/>
<typeAlias alias="Post" type="domain.blog.Post"/>
<typeAlias alias="Section" type="domain.blog.Section"/>
<typeAlias alias="Tag" type="domain.blog.Tag"/>
typeAliases>
当这样配置时,Blog 可以用在任何使用 domain.blog.Blog 的地方。
也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,比如:
<typeAliases>
<package name="domain.blog"/>
typeAliases>
我们需要告诉 MyBatis 到哪里去找到SQL映射语句,这里有四种方法:
<mappers>
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
<mapper resource="org/mybatis/builder/BlogMapper.xml"/>
<mapper resource="org/mybatis/builder/PostMapper.xml"/>
mappers>
<mappers>
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
<mapper url="file:///var/mappers/BlogMapper.xml"/>
<mapper url="file:///var/mappers/PostMapper.xml"/>
mappers>
<mappers>
<mapper class="org.mybatis.builder.AuthorMapper"/>
<mapper class="org.mybatis.builder.BlogMapper"/>
<mapper class="org.mybatis.builder.PostMapper"/>
mappers>
<mappers>
<package name="org.mybatis.builder"/>
mappers>
使用resource方式的映射文件可以任意取名而且放置的位置也可以不放在同一个包下!
而package、class方式必须满足以下两点,否则,将报BindingException异常:
当我们在mapper中使用package加载sql映射文件时,使用的就是这个loadXmlResource方法。而这个方法中的逻辑就是,拿到mapper接口的class对象,将mapper接口的全限定名中的.
替换为/
,然后尾部加上.xml
,然后使用应用类加载器通过流读取这个同文件夹下的xml文件。