Mybaits学习-2
本节解决上一课的小问题,以及谈谈MyBatis的配置文件。
1.接口式编程
在上一节中我们简单的使用了Mybaits提供的基础方法实现了一个数据的查找,我们使用SqlSession实例的selectOne方法传递在Mapper中的sql语句以及对应的参数,并把返回的类交给Dao,这次我们来说一个更常用的方法,接口式的方法,首先们要在创建一个接口:
package com.snake_lvyonghao.MyBatis.Dao;
import com.snake_lvyonghao.MyBatis.bean.Employee;
public interface EmpioyeeMapper {
public Employee getEmpById(Integer id);
}
接口中的方法返回类型就是我们持久层的类,参数当然是根据操作的具体要求而定,比如在这里我想要根据ID去查询他的所有信息,我的参数就是Integer id
。
再回到我们上一节中的Mapper配置文件,当初我们的namespace是随便写的,现在我们要把它改成我们接口的包路径,比如我的是com.snake_lvyonghao.MyBatis.Dao.EmpioyeeMapper
,我的sql语句的id改成接口方法的名字,这样就可以了:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.snake_lvyonghao.MyBatis.Dao.EmpioyeeMapper">
<!--
namespace名称空间指定为全类名
id唯一标示,指定为接口的方法
resultType,返回值类型
#{id}从传递过来的参数中取出id值-->
<select id="getEmpById" resultType="com.snake_lvyonghao.MyBatis.bean.Employee">
select id,last_name lastName,email,gender from tbl_employee where id = #{id}
</select>
</mapper>
然后回到我们的MyBatistest中,我们在写一个Demo,创建sqlSessionFactory对象,创建SqlSession对象这些和以前都是一样的,首先我们要创建一个接口的实例,用Sqlsession对象的getMapper方法初始化,再创建持久层的对象用接口的对象的方法获得实例(方法的返回值是DaoImpl类还记得吗?)。在这里我们发现了一个严重的问题,明明我们在接口中的方法没有去写,为什么这样的操作能够成功呢?实际上SqlSession的getMapper方法传回来是一个代理对象,下面是具体的实现;
package com.snake_lvyonghao.MyBatis.test;
import com.snake_lvyonghao.MyBatis.Dao.EmpioyeeMapper;
import com.snake_lvyonghao.MyBatis.bean.Employee;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
public class MyBatistest {
/**
* 1.根据xml配置文件(全局配置文件)创建一个SqlSessionFactory对象
* 有一些数据源运行信息
* 2.sql映射文件;配置可每一个sql,以及sql的封装规则,
* 3.将sql映射文件注册在全局配置文件当中
* 4.写代码
* 1)根据全局配置文件得到SqlSessionFactory
* 2)使用sqlSession工厂,获取到sqlSession对象使用它来执行增删改查
* 一个sqlSession就是代表和数据库的一次会话,用完关闭
* 3)使用sql的唯一标示告诉MyBatis执行那个sql,sql都保存在映射文件当中
* @throws IOException
*/
@Test
public void test() throws IOException {
String resource = "Mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory =
new SqlSessionFactoryBuilder().build(inputStream);
//获取sqlSession实例,能直接执行已经映射的sql语句
SqlSession opensession = sqlSessionFactory.openSession();
//两个参数,sql的唯一标示,执行sql的参数
try {
Employee e = opensession.selectOne("org.mybatis.EmployeeMapper.selectEmp",1);
System.out.println(e);
}finally {
opensession.close();
}
}
//获取一个SqlSessionFactory对象
public SqlSessionFactory getSqlSessionFactory() throws IOException {
String resource = "Mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
return new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void test1() throws IOException{
//1.获取SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
//2.获取SqlSession对象,
SqlSession openSession = sqlSessionFactory.openSession();
//3.获取接口的实现类对象
//会为接口创建UI个代理对象,代理对象去执行增删改查
try {
EmpioyeeMapper mapper = openSession.getMapper(EmpioyeeMapper.class);
Employee employee = mapper.getEmpById(1);
System.out.println(mapper.getClass());
System.out.println(employee);
} finally {
openSession.close();
}
}
}
2.小总结
- 通过MyBatis我们把Dao和方法分开,以前是一个Dao对应一个DaoImpl,现在是一个Mapper对应一个xxMapper.xml
- SqlSession代表和数据库的一次会话,用完就得关闭
- SqlSesson和connction一样都是非线程安全,就不可以写成
private SqlSession sqlsession
每次使用都应该获取新的对象 - mapper接口没有实现类,但是myBatis会为这个接口生成一个代理对象(将接口和xml绑定)
- 两个重要配置文件:全局配置文件,sql映射文件。
3.MyBatis-全局配置文件
在MyBatis配置文件中我们能做很多事情,下面我就为大家介绍配置文件的使用,配置文件是XML格式,我们通过<>标签的形式对XML进行配置,如何能够按照MyBatis配置文件的格式配置呢?我们只要在XML文件的开头写上Mybatis的约束就好了,<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
.
properties(不常用)
properties它可以通过Properties file来完成对数据库链接信息的配置:
<properties resource="org/mybatis/example/config.properties">
<property name="username" value="dev_user"/>
<property name="password" value="F2Fa3!33TYyg"/>
</properties>
-----------------------------
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
settings
在这个标签里面都是一些MyBatis的设置,通过name,value来配置类似这样的(官方文档里面找的):
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="multipleResultSetsEnabled" value="true"/>
<setting name="useColumnLabel" value="true"/>
<setting name="useGeneratedKeys" value="false"/>
<setting name="autoMappingBehavior" value="PARTIAL"/>
<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value="25"/>
<setting name="defaultFetchSize" value="100"/>
<setting name="safeRowBoundsEnabled" value="false"/>
<setting name="mapUnderscoreToCamelCase" value="false"/>
<setting name="localCacheScope" value="SESSION"/>
<setting name="jdbcTypeForNull" value="OTHER"/>
<setting name="lazyLoadTriggerMethods"
value="equals,clone,hashCode,toString"/>
</settings>
在官方文档中有着对setting能配置的东西有完整介绍,太多了我就不放了,你问我官方文档在哪里?下载的MyBatis里面得PDF就是他的官方文档,其中的ConfigurationXML讲的就是咱的配置文件。
typeAliase
别名处理器,可以为我们经常用java类型的起一个别名,不区分大小写,type属性就是要起别名的的类型全类名,默认别名就是类名小写,或者使用alisa属性起一个新的别名。
<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>
你也可以批量起别名,他可以为某个包下的所有类起别名,name属性指定包名(默认方法)
<typeAliases>
<package name="domain.blog"/>
</typeAliases>
为了防止包下的子包有着相同的类名导致别名冲突,我们可以采用给类加上@Alias(“”)注解的方式去起别名。
@Alias("author")
public class Author {
... }
typeHandlers
类型处理器,在做数据库类型和MyBatis类型的适配的时候,会使用typeHanlders来完成。在官方文档中有着很多的介绍,我会在后面给出更详细的解释,现在知道有这么一个东西就好。
pugins
插件等到学完MyBatis运行机制和运行原理后我们才用得上插件这个功能,先做一个简单的介绍,MyBatis可以拦截到sql的核心语句,这个功能就是通过插件来实现,插件就是拦截这四个对象:
- Executor 执行器(update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
- ParameterHandler 参数处理器(getParameterObject, setParameters(预编译设置参数))
- ResultSetHandler 结果集处理器(handleResultSets, handleOutputParameters)
- StatementHandler sql处理器(prepare, parameterize, batch, update, query)
学过JDBC的应该对以上的方法很眼熟,我们到时候再说。
enviroments
MyBatis的多种环境配置,根据不同的使用使用不同的环境,比如开发时的测试环境,和正式上线后的正式环境其中每一个enviroment配置一个具体的环境信息,我们看着代码来说吧:
<environments default="development">
<environment id="development">
<transactionManager type="JDBC">
<property name="..." value="..."/>
</transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
先说说environment的id属性,如何切换不同的环境配置呢,当然是通过environments的default属性,default属性值就是你所要使用的环境id。 在每一个environment中都需要有transactionManager标签(事务管理器),type属性值填写事务管理器的名称JDBC/MANAGED,当然在后面我们会之用SPring的事务管理代替这个,dataSource(数据源)标签,type属性的值填写UNPOOLED|POOLED|JNDI,分别是不使用连接池,使用链接池,以及JNDI(同样会使用Spring去代替他)。
databaseldProvider
用来告诉MyBatis我们使用的是哪个厂商的数据库,让sql支持多数据库厂商。
<databaseIdProvider type="DB_VENDOR">
<!--为不同的数据库厂商起别名-->
<property name="SQL Server" value="sqlserver"/>
<property name="MySQL" value="mysql"/>
<property name="Oracle" value="oracle" />
</databaseIdProvider>
这些起好名字怎么去使用呢,我们在sql映射文件中sql语句标签中添加M
mappers
将sql映射文件注册到全局当中,在写Helloworld式我们就使用过他了,我们当时使用的是resource属性这个是类路径下的映射文件,当然你也可以使用url属性应用网络路径或者磁盘路径下的sql映射文件,还有一个class属性,他是引用(注册)接口,
- 有sql映射文件,映射文件必须喝接口同名,病房在于接口同一目录下。
- 没有sql映射文件,所有sql都是利用注释写在接口上的
批量注册:使用package标签,name属性写入包路径。
<mappers>
<mapper class="com.snake_lvyonghao.MyBatis.Dao.EmployeeMapperAnnotation"/>
<mapper resource="EmployeeMapper.xml"/>
<package name="com.snake_lvyonghao.MyBatis.Dao"/>
</mappers>
package com.snake_lvyonghao.MyBatis.Dao;
import com.snake_lvyonghao.MyBatis.bean.Employee;
import org.apache.ibatis.annotations.Select;
public interface EmployeeMapperAnnotation {
@Select("select * from tbl_employee where id=#{id}")
public Employee getEmpById(Integer id);
}
推荐:重要的,复杂的Dao接口我们来写sql映射文件,不重要简单的Dao接口为了开发快速我们使用注解的方式,因为sql映射文件不用去修改源代码。
4.PS
一个小的提示,我们所有的标签其实是有顺序的,必须按照官方文档的顺序填写,不然会报错。 SSM框架源码