一:对象关系设计
MyBatis重点了解: 多对一 一对多 多对多
对象关系设计的重点图:
泛华关系:
其实就是继承关系,比如类和类之间,接口和接口之间,使用extends表示.
在UML中,继承通常是使用空心三角+实线来表示.
实现关系:
其实就是实现关系,存在于类和接口之间,使用implements表示.
在UML中,实现通常是使用空心三角+虚线来表示.
依赖关系:
表示一个类依赖于另一个B类的定义,如果A对象离开了B对象,A对象就不能正常编译,则A对象依赖B对象(A类中使用到了B对象)
在UML中依赖通常使用虚线箭头表示.
继承关系表的三种设计方法:
关联关系:
A对象依赖B对象,并且把B对象作为A的一个成员变量,则A和B存在关联关系.
在UML中关联通常使用实际箭头表示.
按照多重性分:
1):一对一:一个A对象属于一个B对象,一个B对象属于一个A对象.
2):一对多:一个A对象包含多个B对象.
3):多对一:多个A对象属于一个B对象,并且每个A对象只能属于一个B对象.
4):多对多:一个A对象属于多个B对象,一个B对象属于多个A对象.
按照导航性分:如果通过A对象中的某一个属性可以访问到B对象,则A可以导航到B.
1):单向:只能从A通过属性导航到B,B不能导航到A.
2):双向:A可以通过属性导航到B,B也可以通过属性导航到A.
判断方法:
1:判断都是从对方的实例上面来看的.
2:判断关系必须确定一对属性.
3:判断关系必须确定具体需求.
对象关系之一对一关系的表设计:
多对一的关系设计:
多对多的关系设计:
聚合关系:
是一种"弱拥有"关系,表示为has-a.
表示整体和个体的关系,整体和个体之间可以相互独立存在,一定是有两个模块来分别管理整体和个体.
如果A和B是聚合关系,它并不是一个独立的整体,A和B的生命周期可以是不同的,通常B也是会作为A的成员变量存在.
在UML中聚合通常是使用空心菱形+实线箭头来表示.
组合关系:
是一种强聚合关系,是一种"强拥有"关系,表示为contains-a.
整体和个体不能独立存在,一定是在一个模块中同时管理整体和个体,声明周期必须相同(级联).
级联(cascade):把主对象的操作遍历的在每一个从对象上面执行相同的操作.
二:对象关系映射
多对一关联映射:跟多查询映射
一对多:查看代码
多对多:查看代码
额外SQL:
<!-- 当结果集中的列名和对象的属性名称不匹配 处理结果集 -->
<resultMap id="BaseResultMap" type="Employee" >
<id column="id" property="id"/>
<result column="name" property="name"/>
<!-- 额外SQL的配置方式
association元素:配置单一元素的关联关系
select属性:发送的额外SQL
column属性:将指定列的值传递给额外的SQL
-->
<association column="dept" property="dept" javaType="Department"
select="cn.wolfcode.mybatis.hello.mapper.DepartmentMapper.get"
/>
</resultMap>
N+1问题:
内连映射:也就是多表查询:可以解决N+1的问题:
<resultMap id="BaseResultMap" type="Employee" >
<id column="id" property="id"/>
<result column="name" property="name"/>
<!--处理关联对象-->
<association property="dept" javaType="Department" columnPrefix="d_">
<id column="d_id" property="dept.id"/>
<result column="d_name" property="dept.name"/>
</association>
</resultMap>
MyBatis的延迟加载和最佳实践
配置mybatis-config.xml文件中<setting></setting>内
<!-- 开启延迟加载功能 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 设置不要积极地去查询关联对象 -->
<setting name="aggressiveLazyLoading" value="false"/>
<!-- 延迟加载触发方法 -->
<setting name="lazyLoadTriggerMethods" value="clone"/>
<!--
在开发中:
针对单属性对象,使用association元素,通常直接使用多表查询操作,也就是使用内连查询.
针对集合属性对象,使用collection元素,通常使用延迟加载也就是额外SQL处理.
-->
在并发中:
针对属性对象,使用association元素,通常直接使用多表查询操作,也就是使用内联查询.
针对集合属性对象,使用collection元素,通常使用延迟加载,也就是额外SQL处理.
缓存机制:
一级缓存跟二级缓存:
启动二级缓存:
拷贝jar包:
mybatis-ehcache-1.0.3.jar它是mybatis的桥梁
ehcache-core-2.6.8.jar
日志文件的拷贝
slf4j-log4j12-1.7.21.jar它是下面俩个的桥梁
slf4j-api-1.6.1.jar
log4j-1.2.17.jar
mybatis-config.xaml:
<setting>
<!-- 启用二级缓存,缺省已经启用 -->
<setting name="cacheEnabled" value="true"/>
</setting>
mapper文件中设置:
<!-- 使用的EhCache技术 -->
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
ehcache.xml文件:
<ehcache>
<!-- 指定硬盘的缓存目录 -->
<!-- <diskStore path="D:/temp/ehcache"/> -->
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="3"
timeToLiveSeconds="5"
overflowToDisk="true"
/>
<!-- 设置默认的缓存区
maxElementsInMemory="10000" 设置最大的缓存对象数量
eternal="false" 设置缓存数据是否过期:true表示永远不过期;false允许过期,
通过timeToIdleSeconds和timeToLiveSeconds属性控制过期
timeToIdleSeconds="20" 对象在缓存区中空闲的时间,单位秒.
timeToLiveSeconds="120" 对象在缓存区中一共存活的时间,单位秒.
overflowToDisk="true" 对象超过最大的缓存数量,将数据往硬盘上缓存.
-->
<!-- 自定义区域的Cache, 填写不同的mapper-->
<cache name="cn.wolfcode.mybatis.hello.mapper.TeacherMapper"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="4"
timeToLiveSeconds="5"
overflowToDisk="true"
/>
</ehcache>
插件的xml文件中的属性值表示什么:
三:MyBatis Generator
MyBatis Generator简称MBG:是一个专门为Batis,MyBatis框架使用者提供的代码生成器,可以快速的根据表
生成对应的模型对象,Mapper接口,Mapper文件,甚至生成QBC风格查询对象.
MyBatis Generator的使用:
1:拷贝jar包
2:提供一个MGB的配置generatorConfig.xml包含了生成代码和配置的参数.
3:运行MGB;
方式一:使用java代码来运行(代码不需要大家写,直接用)
方式二:使用Maven插件运行.
generatorConfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="mysql" defaultModelType="hierarchical" targetRuntime="MyBatis3Simple" >
<!-- 生成的java文件的编码 -->
<property name="javaFileEncoding" value="UTF-8"/>
<property name="beginningDelimiter" value="'"/>
<property name="endingDelimiter" value="'"/>
<!-- 注释生成器 -->
<commentGenerator>
<property name="suppresssDate" value="true" />
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<!-- 必须要有的,使用这个配置链接数据库@TODO:是否可以扩展 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/mybatisdemo"
userId="root"
password="111111">
</jdbcConnection>
<!-- 生成domain对象 -->
<javaModelGenerator targetPackage="cn.wolfcode.mybatis.demo.domain" targetProject="src">
<property name="enableSubPackages" value="true" />
</javaModelGenerator>
<!-- 生成Mapper文件 -->
<sqlMapGenerator targetPackage="cn.wolfcode.mybatis.demo.mapper" targetProject="resources">
<property name="enableSubPackages" value="true" />
</sqlMapGenerator>
<!-- 生成Mapper 接口 -->
<javaClientGenerator targetPackage="cn.wolfcode.mybatis.demo.mapper" type="XMLMAPPER" targetProject="src">
<property name="enableSubPackages" value="true" />
</javaClientGenerator>
<!-- ============================================================================= -->
<table tableName="systemuser" delimitIdentifiers="true" domainObjectName="SystemUser" >
<property name="useActualColumnNames" value="true"/>
<generatedKey column="id" sqlStatement="JDBC" />
</table>
<!-- ============================================================================= -->
</context>
</generatorConfiguration>
//java启动代码
public class Generator {
public static void main(String[] args) throws Exception {
//MBG执行过程中的警告信息
List<String> warnings = new ArrayList<String>();
//生成代码重复时,是否覆盖源代码
boolean override = false;
InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("generatorConfig.xml");
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(in);
DefaultShellCallback callback = new DefaultShellCallback(override);
//创建MBG
MyBatisGenerator mbg = new MyBatisGenerator(config,callback,warnings);
mbg.generate(null);
//输出警告信号
for (String warn : warnings) {
System.out.println(warn);
}
}
}
MyBatis Generator的QBC查询
QBC风格:Query By Criteria,一种查询方式,比较面向对象的,看不到任何SQL语句.在这里主要由Criteria,
Example组成,使用面向对象的方式去拼写查询条件,一般的适用于简单查询
只需要吧generator-Config.xml文件中的第一行中
<context id="mysql" defaultModelType="hierarchical" targetRuntime="MyBatis3Simple" >
targetRuntime="MyBatis3Simple"去掉 或者 只去掉Simple 即可
开发中还是喜欢带Simple的风格,因为自己写SQL在开发中好一些!
四:插件开发
MyBatis执行流程总结1:
MyBatis执行流程图2:
MyBatis执行流程图3:
PageHelper插件
1:先拷贝jar包:
jsqlparser-0.9.5.jar
pagehelper-5.0.0.jar
2:然后mybatis-config.xml中添加
<!-- 配置插件的位置,在环境上面 -->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!-- config params as the following -->
<property name="param1" value="value1"/>
</plugin>
</plugins>
可以查看手册学习
插件如何使用
public class EmployeeServiceImpl implements IEmployeeService{
private EmployeeMapper employeeMapper = MyBatisUtil.getMapper(EmployeeMapper.class);
public PageInfo<?> query(QueryObject qo) {
PageHelper.startPage(qo.getCurrentPage(), qo.getPageSize());
List<Employee> list = employeeMapper.queryForList(qo);
return new PageInfo<>(list);
}
}
pageInfo的使用:
并且Mapper.xml文件中的的代码也不需要添加LIMIT参数:
<!-- 查询结果集 -->
<select id="queryForList" resultType="Employee">
Select id,name,sn,salary,deptId FROM employee
<where>
<if test="keyword != null and keyword != ''">
<bind name="keywordLike" value="'%'+keyword+'%'"/>
AND (name like #{keywordLike} OR sn LIKE #{keywordLike})
</if>
<if test="minSalary!=null">
AND salary >= #{minSalary}
</if>
<if test="maxSalary!=null">
AND salary <= #{maxSalary}
</if>
<if test="deptId > 0">
AND deptId = #{deptId}
</if>
</where>
</select>
测试类:
@Test
public void test1() throws Exception {
IEmployeeService service = new EmployeeServiceImpl();
QueryObject qo = new EmployeeQueryObject();
qo.setCurrentPage(3);
qo.setPageSize(2);
PageInfo<?> pageInfo = service.query(qo);
System.out.println(pageInfo.getTotal());
for(Object o : pageInfo.getList()){
System.out.println(o);
}
}