mybatis介绍
mybaits框架不屏蔽sql,sql可以由开发人员进行编写。并且支持动态sql功能。允许根据不同条件来组装sql语句。mybatis还支持面向接口编程,只需要接口+xml或者注解就可以通过动态代理的方式创建映射器,来执行相应的操作。
mybatis核心组件
SqlSessionFactoryBuilder:通过创造者模式来创建SqlSessionFactory对象,他的生命周期应该仅限定在方法内,在创建SqlSessionFactory之后就应该消失了。
SqlSessionFactory:用来生产SqlSession的工厂对象,生命周期应该和mybatis相同。
SqlSession:SqlSession与Connection类似,代表一个数据库连接资源。通过SqlSession对象可以执行Sql语句,可以控制事务,可以用来获取Mapper映射器。
Mapper(映射器):映射器是最复杂的组件,它由一个接口和xml文件或者注解组成。他可以配置映射规则,进行sql语句的配置,还可以进行缓存配置和动态sql配置。
Mybatis的配置
properties
引入properties文件
<properties resource="路径"/>
在xml中直接配置
<properties>
<property name="key" value="value"/>
</properties>
然后就可以通过${属性名}的方式来引用了。
settings
<settings>
<setting name="" value=""/>
</settings>
可以设置一些影响mybatis运行的参数。
typeAliases
<typeAliases>
<typeAlias type="全限定类名" alias="别名"/>
</typeAliases>
可以给比较长的对象名或者不容易理解的名字定义一个别名。
TypeHandler类型转换器
mybatis中已经写好了常用的类型转换器,一般情况下并不需要我们去配置。类型转换去就是将java类型与jdbc类型进行转换。自定义的类型转换器需要实现TypeHandler接口。有时候我们在进行枚举类型与jdbcType进行转换时会用到自定义类型转换器。
public class MyTypeHandler implements TypeHandler<SEXEnum> {
//给预编译的sql设置参数
public void setParameter(PreparedStatement preparedStatement, int i, SEXEnum sexEnum, JdbcType jdbcType) throws SQLException {
if(sexEnum == SEXEnum.BOY){
//1代表男性
preparedStatement.setInt(i,1);
}else{
//2代表女性
preparedStatement.setInt(i,2);
}
}
//根据名字获取
public SEXEnum getResult(ResultSet resultSet, String s) throws SQLException {
Integer sex = (Integer) resultSet.getObject(s);
if (sex == 1){
return SEXEnum.BOY;
}else{
return SEXEnum.GIRL;
}
}
//根据下标获取
public SEXEnum getResult(ResultSet resultSet, int i) throws SQLException {
Integer sex = (Integer) resultSet.getObject(i);
if (sex == 1){
return SEXEnum.BOY;
}else{
return SEXEnum.GIRL;
}
}
//存储过程
public SEXEnum getResult(CallableStatement callableStatement, int i) throws SQLException {
Integer sex = (Integer) callableStatement.getObject(i);
if (sex == 1){
return SEXEnum.BOY;
}else{
return SEXEnum.GIRL;
}
}
}
ObjectFactory对象工厂
对象工厂将结果集包装成我们需要的bean对象。对象工厂已经由mybatis定义好了,一般不需要我们进行更改。
environments(运行环境)
<environments default="">
<environment id="">
<transactionManager type=""></transactionManager>
<dataSource type="">
<property name="" value=""/>
</dataSource>
</environment>
</environments>
environments中可以对运行环境进行配置,transactionManager可以进行事务配置,一般填JDBC。dataSource可以用来配置数据源。type可以用来配置是否用连接池。
映射器
映射器中是mybatis中既复杂又十分重要的一个组件。持久层的开发中绝大多数时间都是在配置映射器。
其中select insert update delete四个标签就对应着对数据库进行增删改查操作。
select标签中可以配置的属性
select的返回值需要映射成bean对象。我们可以通过自动映射、驼峰映射、resultmap的方式进行映射。
自动映射是默认开启的,驼峰映射需要在settings中配置开启,resultmap的方式需要自行配置映射的对象,并在select中进行引入。
在接口中传入参数时,可以传入对象也可以传入普通变量。如果要传入多个参数的话,需要用@Param来进行配置。
insert
insert的返回值是一个整数,代表操作的数据的行数。
有时主键时数据库自动生成的,但是我们又需要在插入数据后获取这个生成的逐渐,我们可以通过配置UserGeneratedKey和KeyProperty的方式进行配置。KeyProperty代表回填到哪个属性中。
也可以通过selectKey标签进行获取主键的操作。
<insert id="" parameterType="" useGeneratedKeys="true" keyProperty="id">
</insert>
<insert id="" parameterType="" >
<selectKey keyProperty="id" order="AFTER">
select Last_insert_id();
</selectKey>
</insert>
Update和Delete
更新和删除比较简单,执行后的返回值都是一个整数,代表更改的数据行数。
sql
sql标签可以自定义一段可以重用的sql段,然后在需要的地方引用。还可以通过${}来引入属性。
<sql id="selectAll">
select * from ${table}
</sql>
<select id="" parameterType="" resultType="" >
<include refid="selectAll">
<property name="table" value="user"/>
</include>
</select>
resultMap
resultMap中还可以配置级联操作。
<resultMap id="student" type="com.User" >
<!--主键-->
<id property="id" column="id"/>
<!--普通属性映射-->
<result property="name" column="name"/>
<result property="sex" column="sex"/>
<!--如果User没有无参构造器就需要配置这个-->
<!--<constructor>
<arg name="" column=""/>
</constructor>-->
<!--一对一级联 column参数-->
<association property="school" column="id" select="com.set.FindSchoolByUid"/>
<!--一对多级联-->
<collection property="friends" column="id" select="com.set.FindFriendsByUid" />
<!--鉴别器 使用sex属性进行鉴别-->
<discriminator javaType="String" column="sex">
<case value="男" resultMap="boy"></case>
<case value="女" resultMap="girl"></case>
</discriminator>
</resultMap>
<resultMap id="boy" type="" extends="student">
<association property="boyObject" column="id" select=""/>
</resultMap>
<resultMap id="girl" type="" extends="student">
<association property="girlObject" column="id" select=""/>
</resultMap>
多对多级联可以通过两个一对多级联的方式来实现。
而且级联的话很容易出现N+1问题,即查询了多余的数据。这时我们可以通过配置延迟加载来解决这个问题
<settings>
<!-- 打开延迟加载的开关默认为false,将所有的级联都设置为延迟加载 -->
<setting name="lazyLoadingEnabled" value="true" />
<!-- 这个相当于是层级的延迟加载。默认为true,如果为true的话,会将查询对象的下一级的级联也查询出来-->
<setting name="aggressiveLazyLoading" value="false" />
</settings>
可以在级联操作处设置fetchType="eager"将延迟加载关掉。