SqlSessionFactoryBuilder ->SqlSessionFactory->SqlSession->SQL Mapper
SqlSessionFactoryBuilder :根据配置生成SqlSessionFactory , 构建完所有SqlSessionFactory
SqlSessionFactory:依靠工厂生成SqlSession ,单例,整个生命周期
SqlSession:可以发送SQL执行并返回结果,也可以获取Mapper接口 及时关闭
SQL Mapper:java interface+XML 给出sql映射规则,发送SQL执行并返回结果 一个SqlSession事务方法中使用,然后废弃
SqlMapConfig.xml 全局配置文件
properties(属性)
settings(全局配置参数)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境集合属性对象)
–environment(环境子属性对象)
----transactionManager(事务管理)
----dataSource(数据源)
----mappers(映射器)
db.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=root
/*
其中 properties 配置分为 1.xml中 2.db.properties 3.程序参数 ,优先级由低到高。
*/
相应的SqlMapConfig.xml
typeAliases 不区分大小写
<typeAliases>
<!-- 单个别名定义 -->
<typeAlias alias="user" type="com.pojo.User"/>
<!-- 批量别名定义,扫描整个包下的类,别名为类名(首字母大小写都可以) -->
<package name="com.pojo"/> //配合 @Alias("user") 为空则 首字母变小写 如:UserType -> userType
</typeAliases>
typeHandlers 负责javatype与数据库类型转换 ,可自定义,如枚举类型转化,性别 0 men 1 weman
environments 数据源配置
<environments default="1">
<environment id="1">
<transactionManager type="JDBC">
<property name="autoCommit" value="false"/>
</transactionManager>
<dataSource type="POLLED"> //POLLED UNPOLLED JNDI 也可自定义 type=" 替换即可 "
</property> // name pwd....
</dataSource>
</environment>
<environment id="2">
</environment>
</environments>
select详解
<?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="对应DAO接口">
<select id="对应DAO接口方法名" parameterType=“Integer” resultType="org.chench.test.mybatis.model.Test">
select * from test where id = #{id}
</select>
</mapper>
/* 可以开启驼峰命名自动映射 mapUnderscoreToCamelCase=true
namespace="对应DAO接口"
id="对应DAO接口方法名"
parameterType 类全名、别名,方法参数类型
resultType 查询返回值类型
resultMap 定义数据库表字段与POJO一一对应
*/
传递多个参数
<select id="对应DAO接口方法名" parameterType="map" resultMap="xxx">
select * from test where id = #{id}
</select>
public List<Role> getList(Map<String,String> params);
其中 params.put("name","xxx");
params.put("sex","xxx");
<select id="对应DAO接口方法名" parameterType=“map” resultMap="xxx">
select * from test where name = #{name} and sex=#{sex}
</select>
public List<Role> getList(@Param("userName")String username);
<select id="对应DAO接口方法名" resultMap="xxx">
select * from test where name = #{userName}
</select>
//userName ...与Role属性一致
public List<Role> getList(Role role);
<select id="对应DAO接口方法名" parameterType="org.chench.test.mybatis.model.Role" resultMap="xxx">
select * from test where name = #{userName} and sex=#{sex}
</select>
<resultMap id="唯一" type="对应pojo全限定名">
<id property="id" column="id"></id>
<result property="userName" column="user_name"></result>
</resultMap>
id:标识主键
插入值,并返回插入的主键值 给 传入的对象的对应属性 表设计应该设置为自增
insert into t_tole(name,sex) values(#{roleName},#{sex})
int insertRole(Role role);
Role r = new Role();
r.setName();
r.setSex();
myDao.insertRole®;
sout(r.getId()); //获取插入的记录的 主键id值
当然可以 自定义规则, 如当前表为空则置为1 ,否则当前基础上+2 此时数据库表的自增 关闭
select if(max(id) is null,1,max(id)+2) as newId from t_role
insert into t_tole(id,name,sex) values(#{id},#{roleName},#{sex})
定义参数属性不允许换行
sql元素
<sql id = "role_columns">
id,sex,phone
</sql>
<select parameterType="long" id = "getRole" resultMap="roleMap">
select <include refid="role_columns"/> from role where id = #{id}
</select>
<sql id = "role_columns">
#{prefix}.id,#{prefix}.sex,#{prefix}.phone
</sql>
<select parameterType="string" id = "getRole" resultMap="roleMap">
select
<include refid="role_columns">
<property name="prefix" value="r"></property>
</include>
from role where id = #{id}
</select>
<sql id = "some_include">
select * from <include refid="${tableName}" />
</sql>
resultMap 作用 :定义映射规则、级联更新、定制类型转换器等
<resultMap> //id="唯一" type="对应pojo全限定名"
<constructor> //配置构造方法 有的javabean不存在无参数构造器
<idArg> //注入同时 为主键
</idArg>
<arg>
</arg>
</constructor>
<id/> //表明为主键 <id property="id" column="id"></id>
<result/> //定义映射规则 property="javabean属性" column="sql列名" javaType
// jdbcType typeHandler自定义规则
<association/> //支持级联的一部分 一对一、一对多、多对多 解决一对一
//property="javabean属性" column="传给dao方法的参数" select="指向一个dao方法"
//这个属性在在 ProvienceDao中
//如:省份表 id 名字 别名表 id 别名 AliasDao findById(Integer id)
//javabean id 名字 别名
// property="别名" column ="id" select="com.qmylzx.base.dao.AliasDao"
//select*from provience where id = #{id} select*from alias where id = #{id}
<connection/> //支持级联的一部分 一对一、一对多、多对多 解决一对多
// property="cities" column="id" select="base.dao.findCityByPid"/>
<discriminator> //鉴别器级联 解决多对多
<case/>
</discriminator>
</resultMap>
public class Province {
private Long id;
private String name;
private Alias alias;
private List cities; //城市表中有一个pid字段,该字段表示这个城市是属于哪个省份的
//省略getter/setter
}
public interface CityMapper {
List findCityByPid(Long id);
}
discriminator 定义多个resultMap extends 标记type的javabean继承的父类
<?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="dao.ProvinceMapper">
<resultMap id="provinceResultMapper" type="org.sang.bean.Province">
<id column="id" property="id"/>
<discriminator javaType="int" column="area"> // javaType column 以这个作为区分
<case value="1" resultMap="noodleResultMap"></case>
<case value="2" resultMap="riceResultMap"></case>
</discriminator>
</resultMap>
<resultMap id="noodleResultMap" type="org.sang.bean.Province" extends="provinceResultMapper">
<collection property="foods" column="area" select="org.sang.db.NoodleMapper.findNoodleByArea"/>
</resultMap>
<resultMap id="riceResultMap" type="org.sang.bean.Province" extends="provinceResultMapper">
<collection property="foods" column="area" select="org.sang.db.RiceMapper.findRiceByArea"/>
</resultMap>
<select id="getProvince" resultMap="provinceResultMapper">
SELECT * FROM province
</select>
</mapper>
PS: 使用级联 超过三层 复杂度上升、查询到无用数据,造成性能下降, 为了解决这个问题考虑延迟加载
全局延迟加载:setting中设置 lazyLoadingEnable = true aggressiveLazyLoading=ture
//仅开启延迟加载还是会加载所有信息 , 开启层级加载(aggressiveLazyLoading)后才会只加载一部分,即使用的部分
局部延迟加载association 、connection 属性fetchType eager、lazy
使用map存储结果集 :一般而言,任何select语句都可用map
<select id = "findColorByNote" parameterType="string" resultType="map">
select id color note from t_color where note like concat('%',#{note},'%')
</select>
使用POJO
缓存
系统缓存(一级缓存、二级缓存):默认开启一级缓存,即同一个SQLSession查询后,若未声明需要刷新或无缓存超时,则再次查询,只会从缓存中获取数据,而不会再次发送sql到数据库(相同的mapper、参数和方法)
往往我们需要开启二级缓存,使得在SQLSessionFactory层面上能够提供给各个SQLSession对象共享,
开启二级缓存:POJO需要可序列化(implements Serializable)、并在映射xml文件配置
PS:select语句会缓存、insert、update、delete会刷新缓存,系统使用默认的LRU算法来回收
根据时间表,如NO Flush Interval(无刷新间隔),缓存不会以任何时间顺序来刷新
缓存会存储列表集合或对象的1024个引用
缓存是可读可写的,即对象检索不共享,而且可以安全的被调用者修改
cache 的属性
eviction=“LRU” //回收策略 LRU、FIFO、SOFT软引用(基于GC)、WEAK(这里也是LRU,更积极基于GC)
flushInterva=" " //不配置默认sql执行才刷新缓存
size //引用数目,不适合太大,容易OOM
readOnly //默认为false
type=“com.qmylzx.MyCache” //自定义缓存,如使用redis 只需要实现mybatis 提供的接口类
//以下,在MyCache中若有setHost(String host) 方法,则在初始化的时候会调用
动态SQL
if //单条件分支判定
select id,name,note from t_role where 1=1 and name like concat('%',#{roleName},'%')choose(when、otherwise) //多条件
select id,name,note from t_role where 1=1 and id=#{roleId} and note is not nulltrim(where、set) // 用于处理一些sql拼装问题
where
<select id="findRoles" parameterType="string" resultMap="xxx">
select id,name,note from t_role
<where> //以上 if choose where 1=1 没有会报错,这里可以用 where标签
<if test="roleName!=null and roleName!=''">
and name like concat('%',#{roleName},'%')
</if>
</where>
</select>
trim 去掉一些特殊字符串 prefixOverrides代表要去掉的字符串 prefix代表前缀
<select id="findRoles" parameterType="string" resultMap="xxx">
select id,name,note from t_role
<trim prefix="where" prefixOverrides="and">
<if test="roleName!=null and roleName!=''">
and name like concat('%',#{roleName},'%')
</if>
</trim>
</select>
set 防止更新某列导致的全部字段都要发送一次 ,节省带宽
<update>
update role
<set>
<if test="roleName!=null and roleName!=''">
roleName=#{roleName}
</if>
<if test="sex!=null and sex!=''">
sex=#{sex}
</if>
</set>
where roleId=#{roleId}
</update>
//以上set 可以替换为 <trim prefix="set" prefixOverrides=",">
foreach // 在in语句等列举条件常用
select * from t_user where sex in #{sex} //其中collection为传入参数名称,可以是 数组、list、set等集合 //item是循环中当前元素,index当前元素在集合的下标bind //用于 mybatis 自己的方式 实现自定义的函数语法,而不用关心数据库实现 mysql 的concat与oracle的 ||
<select id="findRoles" parameterType="string" resultMap="xxx">
<bind name="pattern_roleName" value="'%'+roleName+'%'"></bind>
<bind name="pattern_note" value="'%'+note+'%'"></bind>
select id,name,note from t_role
where name like #{pattern_roleName}
and note like #{pattern_note}
</select>
public List<Role> findRole(@Param("roleName")String roleName ,@Param("note")String note);