住房和城乡建设部的网站,网络架构师报考条件,品牌宣传推广文案,能打开国家禁止网站的浏览器java 系列文章 文章目录java 系列文章前言一、Mybatis 入门1.1 认识 框架#xff08;了解#xff09;1.2 认识 ORM#xff08;要知道#xff09;1.3 认识 Mybatis#xff08;要知道#xff09;二、Mybatis 使用2.1 创建maven项目并导入依赖2.2 准备数据库#xff0c;包和…java 系列文章 文章目录java 系列文章前言一、Mybatis 入门1.1 认识 框架了解1.2 认识 ORM要知道1.3 认识 Mybatis要知道二、Mybatis 使用2.1 创建maven项目并导入依赖2.2 准备数据库包和实体类2.3 准备mapper文件映射2.4 运行测试三、Mybatis配置详解3.1 log4j1 和log4j2的使用3.2 事务配置3.3 关于映射文件的加载方式3.4 关于实体类别名处理3.5 关于外部属性配置文件存储数据库链接信息四、Mybatis 普通开发模式4.1 查询的三种模式4.2 Mybatis参数传递的三种方式4.3 Mybatis完成DML全部操作五、Mybatis 代理模式开发5.1 使用mapper代理实现查询5.2 代理模式浅析六. 代理模式下的参数传递问题6.1 多参数传递6.2 模糊查询6.3 自增主键回填6.4 实现DML操作七、动态SQL7.1 If 标签7.2 Where 标签7.3 Choose标签7.4 Set 标签7.5 Trim 标签7.6 Bind 标签7.7 Sql 标签八、Mybatis 多表查询8.1 关联查询8.2 级联查询九、Mybatis 注解开发9.1 使用注解开发十、 缓存10.1 一级缓存10.2 二级缓存10.3 三方缓存十一、逆向工程十二、main目录下XML文件编译问题总结前言
MyBatis是一个半自动ORM框架其本质是对JDBC的封装。使用MyBatis重点需要程序员编写SQL命令不需要写一行JDBC代码。 一、Mybatis 入门
1.1 认识 框架了解 框架Framework是一个框子——指其约束性也是一个架子——指其支撑性。是一个基本概念上的结构用于去解决或者处理复杂的问题。框架这个广泛的定义使用的十分流行尤其在软件概念。 框架( Framework )对于java来说,就是一系列为了解决特定问题而定义的一系列接口和实现类,在组织框架代码时,使用了一系列优秀的设计模式,使代码无论在性能上还是API操作上得到很大提升.框架可以看做是项目开发的半成品,基本的底层操作已经封装完毕,通过框架,程序员可以从底层代码中解脱出来,专注于业务逻辑的完成和性能的优化。框架规定了你的应用的体系结构。它定义了整体结构类和对象的分割各部分的主要责任类和对象怎么协作以及控制流程。框架预定义了这些设计参数以便于应用设计者或实现者能集中精力于应用本身的特定细节。 如果将开发完成的软件比作是一套已经装修完毕的新房那框架就好比是一套已经修建好的毛坯房。用户直接购买毛坯房建筑质量和户型合理有保证还省去了自己建造房屋的时间一举多得。 在开发过程是使用框架同样可以保证减少开发时间、降低开发难度并且还保证设计质量。好比和世界上最优秀的软件工程师是一个项目的并且他们完成的还是基础、全局的工作。想想是不是很嗨的一件事情。 框架还有一个作用是约束。莎士比亚说,“一千个观众眼中有一千个哈姆雷特” 即仁者见仁,智者见智.说每个人都会对作品有不同的理解每个人对待任何事物都有自己的看法一千个人就有可能有一千种不同的看法1000人心中有1000个哈姆雷特。同样的技术解决同样的问题会产生不同流程和风格的解决方案而采用一种框架其实就是限制用户必须使用其规定的方案来实现可以降低程序员之间沟通以及日后维护的成本。 常用的基于JavaEE的三大开源框架已经从SSH、SSH2过渡到了SSMSpringMVC、Spring、MyBatis springBoot 总之框架是一个半成品已经对基础的代码进行了封装并提供相应的API开发者在使用框架是直接调用封装好的API可以省去很多代码编写从而提高工作效率和开发速度。
1.2 认识 ORM要知道
JDBC的缺点需要手动的完成面向对象的Java语言、面向关系的数据库之间数据的转换代码繁琐无技术含量影响了开发效率。如图所示查询是需要手动的将结果集的列数据转换为Java对象的属性而添加操作时需要手动将Java对象的属性转换为数据库表的列字段。关于面向对象的Java语言、面向关系的数据库之间数据的转换必须要做问题在于这个转换是否可以不由开发者来做。可以的。ORM框架就是专门来做这个问题的相当于在面向对象语言和关系数据库之间搭建一个桥梁。ORMObject-Relationl Mapping对象关系映射它的作用是在关系型数据库和对象之间作一个映射这样我们在具体的操作数据库的时候只要像平时操作对象一样操作它就可以了ORM框架会根据映射完成对数据库的操作就不需要再去和复杂的SQL语句打交道了。 另外学习ORM必须知道两个概念持久化、持久层 什么是“持久化” 持久Persistence即把数据如内存中的对象保存到可永久保存的存储设备中如磁盘。持久化的主要应用是将内存中的数据存储在关系型的数据库中当然也可以存储在磁盘文件中、XML数据文件中等等。 什么是 “持久层” 持久层Persistence Layer即专注于实现数据持久化应用领域的某个特定系统的一个逻辑层面将数据使用者和数据实体相关联。之前使用JDBC访问数据库的DAO层后面采用MyBatis访问数据库的mapper层就是持久层。Mybatis是一持久层的款半自动的ORM映射框架
1.3 认识 Mybatis要知道
MyBatis 本是Apache的一个开源项目iBatis, 2010年这个项目由Apache Software Foundation 迁移到了Google Code且改名为MyBatis 。2013年11月迁移到GitHub。iBATIS一词来源于“internet”和“abatis”的组合是一个基于Java的持久层框架。MyBatis 是一款优秀的持久层框架它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录。 精简解释MyBatis是一个半自动ORM框架其本质是对JDBC的封装。使用MyBatis重点需要程序员编写SQL命令不需要写一行JDBC代码。
二、Mybatis 使用
2.1 创建maven项目并导入依赖 创建一个空项目如果创建完发现没有项目关闭从新打开一下即可 设置maven(可以选择导入也可以直接创建maven项目) 在pom.xml中导入MyBatis相关依赖jar文件Mybatis地址 ?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersiongroupIdcom.msb/groupIdartifactIdmybatisTest01/artifactIdversion1.0-SNAPSHOT/versionpackagingjar/packagingdependencies!--mysqlConnector--dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion8.0.16/version/dependency!--mybatis 核心jar包--dependencygroupIdorg.mybatis/groupIdartifactIdmybatis/artifactIdversion3.5.3/version/dependency!--junit--dependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion4.13.1/versionscopetest/scope/dependency!--lombok --dependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdversion1.18.12/versionscopeprovided/scope/dependency/dependencies
/project 安装lombok插件后,重启idea 导入lombok依赖后,单独设置启用注解处理
2.2 准备数据库包和实体类
数据库省略实体类Deptpackage com.msb.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/*** Author: bingwoo*/
Data
AllArgsConstructor
NoArgsConstructor
public class Dept implements Serializable {private Integer deptno;private String dname;private String loc;
} resources目录下 创建 com/msb/mapper目录,然后添加DeptMapper.xml映射文件?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtd
mapper namespaceaaa!--public ListDept findAll(){ }--select idfindAll resultTypecom.msb.pojo.Dept select * from dept/select
/mapperresources目录下准备sqlMapConfig.xml 核心配置文件?xml version1.0 encodingUTF-8 ?
!DOCTYPE configurationPUBLIC -//mybatis.org//DTD Config 3.0//ENhttp://mybatis.org/dtd/mybatis-3-config.dtdconfigurationenvironments defaultdevelopmentenvironment iddevelopmenttransactionManager typeJDBC/dataSource typePOOLEDproperty namedriver valuecom.mysql.cj.jdbc.Driver/property nameurl valuejdbc:mysql://127.0.0.1:3306/mydb?useSSLfalseamp;useUnicodetrueamp;characterEncodingUTF-8amp;serverTimezoneAsia/Shanghai/property nameusername valueroot/property namepassword value密码//dataSource/environment/environments!--加载mapper映射文件--mappersmapper resourcecom/msb/mapper/DeptMapper.xml//mappers
/configuration
2.3 准备mapper文件映射 2.4 运行测试
package com.msb.test;import com.msb.pojo.Dept;
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.After;
import org.junit.Before;
import org.junit.Test;import java.io.IOException;
import java.io.InputStream;
import java.util.List;/*** Author: bingwoo*/
public class Test1 {private SqlSession sqlSession;Beforepublic void init(){SqlSessionFactoryBuilder ssfb new SqlSessionFactoryBuilder();InputStream resourceAsStream null;try {resourceAsStream Resources.getResourceAsStream(sqlMapConfig.xml);} catch (IOException e) {e.printStackTrace();}SqlSessionFactory factoryssfb.build(resourceAsStream) ;sqlSessionfactory.openSession();}Testpublic void testFindAll(){// 调用SQL语句ListDept list sqlSession.selectList(findAll);for (Dept dept : list) {System.out.println(dept);}}Afterpublic void release(){// 关闭SQLSessionsqlSession.close();}}
三、Mybatis配置详解
3.1 log4j1 和log4j2的使用
在mybatis.cfg.xml中配置MyBatis所使用的具体日志实现。如果不指定将自动搜索。可能会搜到log4j但是如果优先搜到了其他的日志实现呢所以还是设置为好。这一来log4j就跑不了了。 log4j1 使用 log4j1
dependencygroupIdlog4j/groupIdartifactIdlog4j/artifactIdversion1.2.17/version
/dependency将log4j.properties文件负责到src下。另外在其中可以将全局的日志级别调高避免大量debug信息的干扰。同时将对映射文件的操作调低可以用来显示SQL语句的调试信息。开发阶段建议启动控制的日志。 #定义全局日志级别调试阶段推荐debug
log4j.rootLoggerdebug,stdout log4j.appender.stdoutorg.apache.log4j.ConsoleAppender
log4j.appender.stdout.TargetSystem.err
log4j.appender.stdout.layoutorg.apache.log4j.SimpleLayoutlog4j.appender.logfileorg.apache.log4j.FileAppender
log4j.appender.logfile.Filed:/msb.log
log4j.appender.logfile.layoutorg.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern%d{yyyy-MM-dd HH:mm:ss} %l %F %p %m%nlog4j1 使用 log4j2
dependencygroupIdorg.apache.logging.log4j/groupIdartifactIdlog4j-core/artifactIdversion2.12.1/version
/dependency将log4j2.xml文件负责到resources下。 ?xml version1.0 encodingUTF-8?
Configuration statusDEBUGAppendersConsole nameConsole targetSYSTEM_ERRPatternLayout pattern%d{YYYY-MM-dd HH:mm:ss} [%t] %-5p %c{1}:%L - %msg%n //ConsoleRollingFile nameRollingFile filenamelog/test.logfilepattern${logPath}/%d{YYYYMMddHHmmss}-fargo.logPatternLayout pattern%d{YYYY-MM-dd HH:mm:ss} [%t] %-5p %c{1}:%L - %msg%n /PoliciesSizeBasedTriggeringPolicy size10 MB //PoliciesDefaultRolloverStrategy max20 //RollingFile/AppendersLoggersRoot levelINFOAppenderRef refConsole //Root/Loggers
/Configuration核心配置文件中可以指定日志打印方式 configurationsettings...setting namelogImpl valueLOG4J/.../settings
/configuration3.2 事务配置
在mybatis核心配置文件中 envirment中 通过transactionManager配置事务的处理策略environment idmysqltransactionManager typeJDBCdatasource typePOOLEDproperty namedriver valuejdbc文件配置地址property nameurl value数据库访问地址property nameusername value账号property namepassword value密码datesource
/environment JDBC – 这个配置直接简单使用了 JDBC 的提交和回滚设置。它依赖于从数据源得到的连接来管理事务范围。MANAGED – 这个配置几乎没做什么。它从来不提交或回滚一个连接。而它会让容器来管理事务的整个生命周期(比如 Spring 或 JEE 应用服务器的上下文) 默认情况下它会关闭连接。然而一些容器并不希望这样, 因此如果你需要从连接中停止它,将 closeConnection 属性设置为 false. mybatis本身并不做事务的处理,交给其他框架去处理事务,如spring
3.3 关于映射文件的加载方式
mapper映射文件的文件路径导入 使用的mapper标签的resource属性网络资源路径 使用的mapper标签的url属性接口的全限定名导入 使用的是mapper标签的class属性 (基于接口的代理模式开发)包扫描形式加载所有的mapper映射文件 使用的是 package标签
3.4 关于实体类别名处理 在mybatis核心配置文件中使用别名处理 !--设置实体类别名--
typeAliases!--通过包扫描给所有的实体类起别名给指定报名下的所有类起别名默认每个实体类的别名是首字母小写的类名Dept deptEmp emp--package namecom.msb.pojo/
/typeAliases 在映射文件的resultType 返回值类型 和paramterType 上就可以使用别名了 select idselectByEmpno resultTypeempselect * from emp where empno 123
/select3.5 关于外部属性配置文件存储数据库链接信息 在resources下准备jdbc.properties属性配置文件 jdbc_drivercom.mysql.cj.jdbc.Driver
jdbc_urljdbc:mysql://127.0.0.1:3306/mydb?useSSLfalseuseUnicodetruecharacterEncodingUTF-8serverTimezoneAsia/Shanghai
jdbc_usernameroot
jdbc_password密码在核心配置文件中引入db.properties属性文件 ?xml version1.0 encodingUTF-8 ?
!-- xml文档约束 约束xml文档中可以有哪些标签,哪些属性,以及标签的包含关系和顺序....
dtd 约束
schema 约束
--
!DOCTYPE configurationPUBLIC -//mybatis.org//DTD Config 3.0//ENhttp://mybatis.org/dtd/mybatis-3-config.dtd
configurationproperties resourcejdbc.properties/propertiessettings!--设置日志处理方式--setting namelogImpl valueLOG4J//settings!--设置实体类别名--typeAliases!--通过包扫描给所有的实体类起别名给指定报名下的所有类起别名默认每个实体类的别名是首字母小写的类名Dept deptEmp emp--package namecom.msb.pojo//typeAliases!--配置数据库链接信息--environments defaultmysql!--数据源1--environment idmysqltransactionManager typeJDBC/!--一个数据源--dataSource typePOOLEDproperty namedriver value${jdbc_driver}/property nameurl value${jdbc_url}/property nameusername value${jdbc_username}/property namepassword value${jdbc_password}//dataSource/environment/environments!--加载映射文件的--mappersmapper resourcecom/msb/mapper/DeptMapper.xml//mappers
/configuration四、Mybatis 普通开发模式
4.1 查询的三种模式 返回单个对象 selectOne !--返回单个对象public Emp findOne();id 相当于方法名resultType 相当于返回值类型sql语句的查询结果用哪个类来进行封装 如果返回值类型是集合,这里写的也是集合中的元素对应的类,不是集合本身作为类型paramaterType 参数类型SQL语句就是具体的方法体的实现--
select idfindOne resultTypeemp select * from emp where empno 7499
/select返回对象List集合 selectList !--
返回多个对象List集合
查询全部的员工信息
public ListEmp findAll()
--
select idfindAll resultTypeempselect * from emp
/select返回对象Map集合 selectMap !--返回多个对象的Map集合
把查询出来的数据中的某一列作为键,整条数据封装的对象作为值
public Mapkey,Emp findEmpMap()
empno,Emp
key,Emp
--
select idfindEmpMap resultTypemapselect * from emp
/select4.2 Mybatis参数传递的三种方式 单个基于基础数据作为参数 ?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtdmapper namespaceEmpMapper2!--参数为一个基本数据类型根据员工工号查询员工的全部信息,返回单个员工对象public Emp findByEmpno(int empno);parameterType 在有参数情况下也是可以省略不写 mybatis 可以根据实际情况自动判断如果要写parameterType 那么就要写对在SQL语句上可以使用${} #{} 代表参数的占位如果参数是单个基本数据类型,{}中名字可以随便写,见名知意${} 代表mybatis底层使用Statment语句对象,参数是以字符串拼接的形式设置#{} 代表mybatis底层使用的preparedStatment语句对象,参数使用?作为占位符处理#{} 以后常用--select idfindByEmpno resultTypeemp parameterTypeintselect * from emp where empno #{empno}/select
/mapper多个基础数据类型的ma集合作为参数 ?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtdmapper namespaceEmpMapper2!--参数为map集合查询指定部门号和指定最低薪资的员工信息20 号部门 且工资在1500以上的员工信息public ListEmp findEmpByDeptnoAndSal(int deptno,double sal); 最好要进行转译处理,参照HTML转译 w3school在线文档中有转译符号对应规则MapString,Object argsnew HashMap();args.put(deptno, 20);args.put(sal, 1500.0);#{}中写的是map集合中,参数的键--select idfindEmpByDeptnoAndSal resultTypeemp parameterTypemapselect * from emp where deptno #{deptno} and sal gt; #{sal}/select
/mapper引用类型作为参数 ?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtdmapper namespaceEmpMapper2!--参数为对象emp deptno sal参数是我们自定义的类型,那么 #{}中写的是参数的属性名--select idfindEmpByDeptnoAndSal2 resultTypeemp parameterTypeempselect * from emp where deptno #{deptno} and sal gt; #{sal}/select
/mapper4.3 Mybatis完成DML全部操作 mapper.xml 映射 ?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtdmapper namespaceEmpMapper3!--增删方法的返回值类型都是intresultType就无需指定了insert update delete 标签中没有resultType但是仍然可以有paramaterType--!-- 增加方法public int addEmp(Emp emp);--insert idaddEmp parameterTypeempinsert into emp values(#{empno},#{ename},#{job},#{mgr},#{hiredate},#{sal},#{comm},#{deptno})/insert
/mapper五、Mybatis 代理模式开发 前面已经使用MyBatis完成了对Emp表的CRUD操作都是由SqlSession调用自身方法发送SQL命令并得到结果的实现了MyBatis的入门。 缺点 不管是selectList()、selectOne()、selectMap()都是通过SQLSession对象的API完成增删改查,都只能提供一个查询参数。如果要多个参数需要封装到JavaBean或者Map中并不一定永远是一个好办法。返回值类型较固定。只提供了映射文件没有提供数据库操作的接口不利于后期的维护扩展。 在MyBatis中提供了另外一种成为Mapper代理或称为接口绑定的操作方式。在实际开发中也使用该方式。下面我们就是要Mapper代理的方式来实现对Emp表的CRUD操作吧还有完成多个参数传递、模糊查询、自增主键回填等更多的技能实现。搭建好的项目框架如图所示相比而言增加了接口EmployeeMapper。但是却会引起映射文件和测试类的变化。 优点: 有接口 模块之间有规范了参数的处理多样了,接口中的方法参数列表由我们自己决定通过代理模式由mybatis提供接口的实现类对象 我们不用写实现类了
5.1 使用mapper代理实现查询 mapper 接口 package com.msb.mapper;import com.msb.pojo.Emp;
import java.util.List;/*** Author: java*/
public interface EmpMapper {/*** 该方法用于查询全部的员工信息* return 全部员工信息封装的Emp对象的List集合*/ListEmp findAll();
} mapper.xml 映射文件 ?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtdmapper namespacecom.msb.mapper.EmpMapper!--1 接口的名字和Mapper映射为文件名字必须保持一致(不包含拓展名)2 Mapper映射文件的namespace必须是接口的全路径名3 sql语句的id必须是对应方法的名4 DeptMapper映射文件应该和接口编译之后放在同一个目录下--!--ListEmp findAll();--select idfindAll resultTypeemp select * from emp/select/mappersqlMapConfig.xml核心配置文件中使用包扫描形式加载所有的映射文件 !--加载mapper映射文件--
mappers!--通过类的全路径去找mapper映射文件--mapper classcom.msb.mapper.EmpMapper/
/mappers 测试代码
package com.msb.test;import com.msb.mapper.EmpMapper;
import com.msb.pojo.Dept;
import com.msb.pojo.Emp;
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.After;
import org.junit.Before;
import org.junit.Test;import java.io.IOException;
import java.io.InputStream;
import java.util.List;/*** Author: bingwoo*/
public class Test1 {private SqlSession sqlSession;Beforepublic void init(){SqlSessionFactoryBuilder ssfb new SqlSessionFactoryBuilder();InputStream resourceAsStream null;try {resourceAsStream Resources.getResourceAsStream(sqlMapConfig.xml);} catch (IOException e) {e.printStackTrace();}SqlSessionFactory factoryssfb.build(resourceAsStream) ;sqlSessionfactory.openSession();}Testpublic void testFindAll(){EmpMapper empMappersqlSession.getMapper(EmpMapper.class);ListEmp emps empMapper.findAll();emps.forEach(System.out::println);}Afterpublic void release(){// 关闭SQLSessionsqlSession.close();}}
5.2 代理模式浅析
mybatis是如何通过代理模式实现查询的这条语句的底层使用了动态代理模式动态创建一个EmployeeMapper的一个代理对象并赋给接口引用。所以在MyBatis中不需要显式提供Mapper接口的实现类这也是简单的地方。
六. 代理模式下的参数传递问题
6.1 多参数传递 单个基本数据类型 !--
单个基本数据类型作为方法参数
#{}中可以随便写,遵循见名知意
Emp findByEmpno(int empno);
--
select idfindByEmpno resultTypeemp select * from emp where empno #{empno}
/select多个基本数据类型 !--
多个基本数据类型作为方法参数
ListEmp findByDeptnoAndSal(Param(detpno) int deptno,Param(sal) double sal);
方式1 arg* arg0 arg1 arg2 数字是索引,从0开始
方式2 param* param1 param2 param3 数字是编号,从1开始
使用别名
ListEmp findByDeptnoAndSal(Param(detpno) int deptno,Param(sal) double sal);
通过Param注解使用别名之后,就不能再使用arg* 但是可以继续使用param*
--
select idfindByDeptnoAndSal resultTypeemp!--select * from emp where deptno #{arg0} and sal #{arg1}--!-- select * from emp where deptno #{param1} and sal #{param2}--!-- select * from emp where deptno #{deptno} and sal #{sal}--
/select单个引用数据类型 !--单个引用类型,{}中写的使用对象的属性名--
select idfindByDeptnoAndSal3 resultTypeemp parameterTypeemp select * from emp where deptno #{deptno} and sal #{sal}
/selectmap集合数据类型 !--
参数是map,{}写键的名字
--
select idfindByDeptnoAndSal2 resultTypeemp parameterTypemap !--select * from emp where deptno #{arg0} and sal #{arg1}--!-- select * from emp where deptno #{param1} and sal #{param2}--select * from emp where deptno #{deptno} and sal #{sal}
/select多个引用数据类型 !--
多个引用类型作为方法参数ListEmp findByDeptnoAndSal4(Param(empa) Emp empa,Param(empb) Emp empb);如果用Param定义了别名,那么就不能使用arg*.属性名,但是可以使用param*.属性名和别名.属性名
--
select idfindByDeptnoAndSal4 resultTypeemp !-- select * from emp where deptno #{arg0.deptno} and sal #{arg1.sal} --select * from emp where deptno #{param1.deptno} and sal #{param2.sal}!-- select * from emp where deptno #{empa.deptno} and sal #{empb.sal}--
/select6.2 模糊查询 在进行模糊查询时在映射文件中可以使用concat()函数来连接参数和通配符。另外注意对于特殊字符比如不能直接书写应该使用字符实体替换。 !--ListEmp getByName(String name);--
select idfindByEname resultTypeemp select * from emp where ename like concat(%,#{name},%)
/select
6.3 自增主键回填 MySQL支持主键自增。有时候完成添加后需要立刻获取刚刚自增的主键由下一个操作来使用。比如结算构造车后主订单的主键确定后需要作为后续订单明细项的外键存在。如何拿到主键呢MyBatis提供了支持可以非常简单的获取。 !-- int addDept(Dept dept);
useGeneratedKeystrue 返回数据库帮我们生成的主键
--
insert idaddDept parameterTypedept useGeneratedKeystrue keyPropertydeptnoinsert into dept values(null,#{dname},#{loc})
/insert!--
keyPropertydeptno 生成的主键值用我们dept对象那个属性存储
--
insert idaddDept2 parameterTypedeptselectKey orderAFTER keyPropertydeptno resultTypeintselect identity/selectKeyinsert into dept values(null,#{dname},#{loc})
/insert6.4 实现DML操作 mapper 接口 /*** 增加员工信息* param emp 存储新增员工信息的Emp对象* return 对数据库数据产生影响的行数*/
int addEmp(Emp emp);/*** 根据员工编号修改员工姓名的方法* param empno 要修改的员工编号* param ename 修改之后的新的员工名字* return 对数据库数据产生影响的行数*/
int updateEnameByEmpno(Param(empno) int empno,Param(ename) String ename);/*** 根据员工编号删除员工信息* param empno 要删除的员工编号* return 对数据库数据产生影响的行数*/
int deleteByEmpno(int empno);mapper.xml !--int addEmp(Emp emp);--
insert idaddEmp insert into emp values(DEFAULT ,#{ename},#{job},#{mgr},#{hiredate},#{sal},#{comm},#{deptno})
/insert
!--int updateEnameByEmpno(Param(empno) int empno,Param(ename) String ename);--
update idupdateEnameByEmpno update emp set ename #{ename} where empno #{empno}
/update
!--int deleteByEmpno(int empno);--
update iddeleteByEmpno delete from emp where empno #{empno}
/update测试数据 package com.msb.test;import com.msb.mapper.DeptMapper;
import com.msb.mapper.EmpMapper;
import com.msb.pojo.Dept;
import com.msb.pojo.Emp;
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.After;
import org.junit.Before;
import org.junit.Test;import java.io.IOException;
import java.io.InputStream;
import java.util.Date;/*** Author: bingwoo**/
public class Test3 {private SqlSession sqlSession;Beforepublic void init(){SqlSessionFactoryBuilder ssfb new SqlSessionFactoryBuilder();InputStream resourceAsStream null;try {resourceAsStream Resources.getResourceAsStream(sqlMapConfig.xml);} catch (IOException e) {e.printStackTrace();}SqlSessionFactory factoryssfb.build(resourceAsStream) ;sqlSessionfactory.openSession();}Testpublic void testAddEmp(){EmpMapper mapper sqlSession.getMapper(EmpMapper.class);mapper.addEmp(new Emp(null, TOM, SALESMAN, 7521, new Date(), 2314.0, 100.0, 10));sqlSession.commit();}Testpublic void testUpdateEnameByEmpno(){EmpMapper mapper sqlSession.getMapper(EmpMapper.class);mapper.updateEnameByEmpno(7938, TOM);sqlSession.commit();}Testpublic void testDeletByEmpno(){EmpMapper mapper sqlSession.getMapper(EmpMapper.class);mapper.deleteByEmpno(7938);sqlSession.commit();}Afterpublic void release(){// 关闭SQLSessionsqlSession.close();}}
七、动态SQL 经常遇到很多按照很多查询条件进行查询的情况比如京东根据不同的条件筛选商品。其中经常出现很多条件不取值的情况在后台应该如何完成最终的SQL语句呢 如果采用JDBC进行处理需要根据条件是否取值进行SQL语句的拼接一般情况下是使用StringBuilder类及其append方法实现还是有些繁琐的。如果你有使用 JDBC 或其它类似框架的经验你就能体会到根据不同条件拼接 SQL语句的痛苦。例如拼接时要确保不能忘记添加必要的空格还要注意去掉列表最后一个列名的逗号。利用动态 SQL 这一特性可以彻底摆脱这种痛苦。 MyBatis在简化操作方法提出了动态SQL功能将使用Java代码拼接SQL语句改变为在XML映射文件中截止标签拼接SQL语句。相比而言大大减少了代码量更灵活、高度可配置、利于后期维护。 MyBatis中动态SQL是编写在mapper.xml中的其语法和JSTL类似但是却是基于强大的OGNL表达式实现的。 MyBatis也可以在注解中配置SQL但是由于注解功能受限尤其是对于复杂的SQL语句可读性很差所以较少使用。
7.1 If 标签
select idfindByCondition resultTypeempselect * from emp where 11if testempno ! nulland empno #{empno}/if
/select7.2 Where 标签
select idfindEmpByCondition resultTypeempselect * from emp wheredeptno #{deptno}if testempno ! nulland empno #{empno}/if/where
/select7.3 Choose标签
select idfindEmpByCondition2 resultTypeempselect * from empwherechoosewhen testempno ! nulland empno #{empno}/when/choose/where
/select7.4 Set 标签
!--int updateEmpByCondtion(Emp emp);--
update idupdateEmpByCondtion update empsetif testename ! null and ename ! , ename #{ename}/if/setwhere empno #{empno}
/update7.5 Trim 标签
select idfindEmpByCondition resultTypeempbind namelikePatten value%parent%/bindselect * from emp where ename like #{likePatten}
/select
7.6 Bind 标签
select idfindEmpByCondition resultTypeempselect * from emptrim prefixwhere prefixOverridesandif testempno ! nulland empno #{empno}/ifif testename ! null and ename ! and ename #{ename}/if/trim
/select7.7 Sql 标签
sql idempColumnempno,ename,job,mgr,hiredate,sal,comm,deptno/sql
sql idbaseSelectselect include refidempColumn/include from emp/sql!--ListEmp findByCondition(Emp emp);--
select idfindByCondition resultTypeempinclude refidbaseSelect/includetrim prefixwhere prefixOverridesandif testempno ! nulland empno #{empno}/ifif testename ! null and ename ! bind namelikePattern value%ename%/and ename like #{likePattern}/ifif testjob ! null and job ! and job #{job}/if/trim
/select八、Mybatis 多表查询
8.1 关联查询 一对一关联查询 ?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtdmapper namespacecom.msb.mapper.EmpMapper!--Emp findEmpJoinDeptByEmpno(int empno);--resultMap idempJoinDept typeemp!--设置emp本身的八个属性的映射关系--id propertyempno columnempno/idresult propertyename columnename/resultresult propertyjob columnjob/resultresult propertysal columnsal/result!--association 处理一对一封装一对一信息关系的标签property emp类的属性名javaType 用哪个类的对象给属性赋值--association propertydept javaTypedeptid columndeptno propertydeptno/idresult columndname propertydname/resultresult columnloc propertyloc/result/association/resultMapselect idfindEmpJoinDeptByEmpno resultMapempJoinDept select * fromemp eleft join dept don e.deptno d.deptnowhere empno #{empno}/select
/mapper一对多关联查询 ?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtd
mapper namespacecom.msb.mapper.DeptMapper!--Dept findDeptJoinEmpsByDeptno(int deptno);--resultMap iddeptJoinEmps typedeptid columndeptno propertydeptno/idresult columndname propertydname/resultresult columnloc propertyloc/result!--处理一对多关系的标签--collection propertyempList ofTypeemp !--设置emp本身的八个属性的映射关系--id propertyempno columnempno/idresult propertyename columnename/resultresult propertyjob columnjob/result/collection/resultMapselect idfindDeptJoinEmpsByDeptno resultMapdeptJoinEmpsselect * from dept d left join emp e on d.deptno e.deptno where d.deptno #{deptno}/select
/mapper多对多关联查询 ?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtd
mapper namespacecom.msb.mapper.ProjectMapper!--Project findProjectJoinEmpsByPid(int pid);--resultMap idprojectJoinEmps typeprojectid columnpid propertypid/idresult columnpname propertypname/resultresult columnmoney propertymoney/result!--一对多 集合属性 collection--collection propertyprojectRecords ofTypeprojectRecordid columnempno propertyempno/idid columnpid propertypid/id!--一对一 --association propertyemp javaTypeempid propertyempno columnempno/idresult propertyename columnename/resultresult propertyjob columnjob/result/association/collection/resultMapselect idfindProjectJoinEmpsByPid resultMapprojectJoinEmpsselect * fromproject pleft join projectrecord pron p.pid pr.pidleft join emp eon e.empno pr.empnowhere p.pid #{pid}/select
/mapper8.2 级联查询
级联查询顾名思义就是利于数据库表间的外键关联关系进行自动的级联查询操作。使用MyBatis实现级联查询除了实体类增加关联属性外还需要在映射文件中进行配置。 立即加载 功能1查询所有员工的信息多对一关联 经过对比发现经过在映射文件中配置测试类的代码大大简化了无序手动进行关联查询和组装数据了。 延迟加载 延迟加载又称按需加载。延迟加载的内容等到真正使用时才去进行加载查询。多用在关联对象或集合中。延迟加载的好处先从单表查询、需要时再从关联表去关联查询大大降低数据库在单位时间内的查询工作量,将工作在时间上的分配更加均匀而且单表要比关联查询多张表速度要快。 延迟加载的设置第一步全局开关在sqlMapConfig.xml中打开延迟加载的开关。配置完成后所有的association和collection元素都生效settingssetting namelazyLoadingEnabled valuetrue/setting nameaggressiveLazyLoading valuetrue/
/settingslazyLoadingEnabled:是否开启延迟加载。是Mybatis是否启用懒加载的全局开关。当开启时所有关联对象都会延迟加载。特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态aggressiveLazyLoading当开启时任何方法的调用都会懒加载对象的所有属性。否则每个属性会按需加载,第二步分开关指定的association和collection元素中配置fetchType属性。eager表示立刻加载lazy表示延迟加载。将覆盖全局延迟设置。 多表查询总结与扩展 resultMap 中的常用属性 属性描述property需要映射到JavaBean 的属性名称。javaTypeproperty的类型一个完整的类名或者是一个类型别名。如果你匹配的是一个JavaBean那MyBatis 通常会自行检测到。column数据表的列名或者列别名。jdbcTypecolumn在数据库表中的类型。这个属性只在insert,update 或delete 的时候针对允许空的列有用。JDBC 需要这项但MyBatis 不需要。typeHandler使用这个属性可以覆写类型处理器实现javaType、jdbcType之间的相互转换。一般可以省略会探测到使用的什么类型的typeHandler进行处理fetchType自动延迟加载selectassociation、collection的属性使用哪个查询查询属性的值要求指定namespaceid的全名称ofTypecollection的属性指明集合中元素的类型即泛型类型 级联查询和多表查询的比较及其选择 级联查询多表查询SQL语句数量多条一条性能性能低性能高延迟加载立即加载、延迟加载只有立即加载灵活性更灵活不灵活SQL难易度见到那复杂选择依据灵活高性能 ResultType和ResultMap使用场景 1)如果你做的是单表的查询并且封装的实体和数据库的字段一一对应 resultType 2)如果实体封装的属性和数据库的字段不一致 resultMap 3)使用N1级联查询的时候 resultMap 4)使用的是多表的连接查询 resultMap 一对一关联映射的实现 1)实例学生和学生证、雇员和工牌 2)数据库层次主键关联或者外键关联参看之前内容 3)MyBatis层次在映射文件的设置双方均使用association即可用法相同 多对多映射的实现 1)实例学生和课程、用户和角色 2)数据库层次引入一个中间表将一个多对多转为两个一对多 3)MyBatis层次 方法1在映射文件的设置双方均使用collection即可不用引入中间类 方法2引入中间类和中间类的映射文件按照两个一对多处理 自关联映射 1)实例Emp表中的员工和上级。一般是一对多关联 2)数据库层次外键参考当前表的主键比如mgr参考empno 3)MyBatis层次按照一对多处理但是增加的属性都写到一个实体类中增加的映射也都写到一个映射文件中
九、Mybatis 注解开发
MyBatis编写SQL除了使用Mapper.xml还可以使用注解完成。当可以使用Auto Mapping时使用注解非常简单不需要频繁的在接口和mapper.xml两个文件之间进行切换。但是必须配置resultMap时使用注解将会变得很麻烦这种情况下推荐使用mapper.xml进行配置。MyBatis支持纯注解方式支持纯mapper.xml方式也支持注解和mapper.xml混合形式。当只有接口没有mapper.xml时在mybatis.cfg.xml中可以通过加载接口类。如果是混合使用时使用。此方式一直是官方推荐方式。如果某个功能同时使用两种方式进行配置XML方式将覆盖注解方式。
9.1 使用注解开发 使用注解没有实现Java代码和SQL语句的解耦 无法实现SQL语句的动态拼接 进行多表的查询时定制ResultMap比较麻烦 public interface DeptMapper {Dept findDeptByDeptno(int deptno);Select(select * from dept where deptno #{deptno})Dept findByDeptno(int deptno);Update(update dept set dname #{dname}, loc #{loc} where deptno #{deptno})int updateDept(Dept dept);Insert(insert into dept values(DEFAULT,#{dname},#{loc}))int addDept(Dept dept);Delete(delete from dept where deptno #{deptno})int removeDept(int deptno);}
XML注解优点1.类和类之间的解耦2.利于修改。直接修改XML文件无需到源代码中修改。3.配置集中在XML中对象间关系一目了然利于快速了解项目和维护4.容易和其他系统进行数据交交换1.简化配置2.使用起来直观且容易提升开发效率3.类型安全编译器进行校验不用等到运行期才会发现错误。4.注解的解析可以不依赖于第三方库可以直接使用Java自带的反射
十、 缓存
缓存cache原始意义是指访问速度比一般随机存取存储器RAM快的一种高速存储器通常它不像系统主存那样使用DRAM技术而使用昂贵但较快速的SRAM技术。缓存的设置是所有现代计算机系统发挥高性能的重要因素之一。是一种临时存储少量数据至内存或者是磁盘的一种技术.减少数据的加载次数,可以降低工作量,提高程序响应速度缓存的重要性是不言而喻的。mybatis的缓存将相同查询条件的SQL语句执行一遍后所得到的结果存在内存或者某种缓存介质当中当下次遇到一模一样的查询SQL时候不在执行SQL与数据库交互而是直接从缓存中获取结果减少服务器的压力尤其是在查询越多、缓存命中率越高的情况下使用缓存对性能的提高更明显。MyBatis允许使用缓存缓存一般放置在高速读/写的存储器上比如服务器的内存能够有效的提供系统性能。MyBatis分为一级缓存和二级缓存同时也可配置关于缓存设置。一级存储是SqlSession上的缓存二级缓存是在SqlSessionFactory(namespace)上的缓存。默认情况下MyBatis开启一级缓存没有开启二级缓存。当数据量大的时候可以借助一些第三方缓存框架或Redis缓存来协助保存Mybatis的二级缓存数据。 10.1 一级缓存
一级存储是SqlSession上的缓存默认开启是一种内存型缓存,不要求实体类对象实现Serializable接口。缓存中的数据使用键值对形式存储数据namespacesqlidargsoffset hash值作为键,查询出的结果作为值 接口代码Test
public void testFindDeptByDetpno() {EmpMapper mapper sqlSession.getMapper(EmpMapper.class);Emp emp mapper.findByEmpno(7521);System.out.println(emp);// 中间发生了增删改或者是调用了SqlSession调用了commit,会自动清空缓存sqlSession.commit();// 增删改的时候调用EmpMapper mapper2 sqlSession.getMapper(EmpMapper.class);Emp emp2 mapper2.findByEmpno(7521);System.out.println(emp2);System.out.println(empemp2);System.out.println(mappermapper2);}10.2 二级缓存 二级缓存是以namespace为标记的缓存可以是由一个SqlSessionFactory创建的SqlSession之间共享缓存数据。默认并不开启。下面的代码中创建了两个SqlSession执行相同的SQL语句尝试让第二个SqlSession使用第一个SqlSession查询后缓存的数据。要求实体类必须实现序列化接口 接口代码 public interface EmpMapper {Emp findByEmpno(int empno);
}映射文件 mapper namespacecom.msb.mapper.EmpMappercache/select idfindByEmpno resultTypeemp useCachetrue flushCachefalseselect * from emp where empno #{empno}/select/mapper测试代码 package com.msb.test;import com.msb.mapper.EmpMapper;
import com.msb.pojo.Emp;
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.After;
import org.junit.Before;
import org.junit.Test;import java.io.IOException;
import java.io.InputStream;/*** Author: bingwoo*/
public class Test3 {private SqlSession sqlSession;private SqlSession sqlSession2;Beforepublic void init(){SqlSessionFactoryBuilder ssfb new SqlSessionFactoryBuilder();InputStream resourceAsStream null;try {resourceAsStream Resources.getResourceAsStream(sqlMapConfig.xml);} catch (IOException e) {e.printStackTrace();}SqlSessionFactory factoryssfb.build(resourceAsStream) ;sqlSessionfactory.openSession();sqlSession2factory.openSession();}Testpublic void testFindDeptByDetpno() {EmpMapper mapper sqlSession.getMapper(EmpMapper.class);Emp emp mapper.findByEmpno(7521);System.out.println(emp);// SqlSession提交之后,才会将查询的结果放入二级缓存sqlSession.commit();EmpMapper mapper2 sqlSession2.getMapper(EmpMapper.class);Emp emp2 mapper2.findByEmpno(7521);System.out.println(emp2);}Afterpublic void release(){// 关闭SQLSessionsqlSession.close();sqlSession2.close();}
}注意其中的commit()执行该命令后才会将该SqlSession的查询结果从一级缓存中放入二级缓存供其他SqlSession使用。另外执行SqlSession的close()也会将该SqlSession的查询结果从一级缓存中放入二级缓存。两种方式区别在当前SqlSession是否关闭了。 执行结果显示进行了两次对数据库的SQL查询说明二级缓存并没有开启。需要进行如下步骤完成开启。 1)全局开关在sqlMapConfig.xml文件中的标签配置开启二级缓存,cacheEnabled的默认值就是true所以这步的设置可以省略。 settingssetting namecacheEnabled valuetrue/
/settings2)分开关在要开启二级缓存的mapper文件中开启缓存 mapper namespacecom.msb.mapper.EmployeeMappercache/
/mapper3)二级缓存未必完全使用内存,有可能占用硬盘存储,缓存中存储的JavaBean对象必须实现序列化接口 public class Emp implements Serializable { }经过设置后查询结果如图所示。发现第一个SqlSession会首先去二级缓存中查找如果不存在就查询数据库在commit()或者close()的时候将数据放入到二级缓存。第二个SqlSession执行相同SQL语句查询时就直接从二级缓存中获取了。 注意 MyBatis的二级缓存的缓存介质有多种多样而并不一定是在内存中所以需要对JavaBean对象实现序列化接口。二级缓存是以 namespace 为单位的不同 namespace 下的操作互不影响加入Cache元素后会对相应命名空间所有的select元素查询结果进行缓存而其中的insert、update、delete在操作是会清空整个namespace的缓存。cache 有一些可选的属性 type, eviction, flushInterval, size, readOnly, blocking。 cache type readOnly evictionflushIntervalsizeblocking/属性含义默认值type自定义缓存类要求实现org.apache.ibatis.cache.Cache接口nullreadOnly是否只读true:给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。false:会返回缓存对象的拷贝(通过序列化) 。这会慢一些,但是安全falseeviction缓存策略 LRU默认 – 最近最少使用移除最长时间不被使用的对象。FIFO – 先进先出按对象进入缓存的顺序来移除它们。SOFT – 软引用基于垃圾回收器状态和软引用规则移除对象。WEAK – 弱引用更积极地基于垃圾收集器状态和弱引用规则移除对象。LRUflushInterval刷新间隔毫秒为单位。默认为null也就是没有刷新间隔只有执行update、insert、delete语句才会刷新nullsize缓存对象个数1024blocking是否使用阻塞性缓存BlockingCache true在查询缓存时锁住对应的Key如果缓存命中了则会释放对应的锁否则会在查询数据库以后再释放锁保证只有一个线程到数据库中查找指定key对应的数据false不使用阻塞性缓存性能更好false如果在加入Cache元素的前提下让个别select 元素不使用缓存可以使用useCache属性设置为false。useCache控制当前sql语句是否启用缓存 flushCache控制当前sql执行一次后是否刷新缓存 select idfindByEmpno resultTypeemp useCachetrue flushCachefalse10.3 三方缓存 分布式缓存框架我们系统为了提高系统并发 和性能一般对系统进行分布式部署集群部署方式不适用分布缓存 缓存的数据在各个服务单独存储不方便系统开发。所以要使用分布式缓存对缓存数据进行集中管理.ehcache,redis ,memcache缓存框架。 Ehcache是一种广泛使用的开源java分布式缓存。主要面向通用缓存javaEE 和 轻量级容器。它具有内存和磁盘存储功能。被用于大型复杂分布式web application这里的三方缓存是作为二级缓存使用导入依赖的jar文件。 dependencygroupIdorg.mybatis.caches/groupIdartifactIdmybatis-ehcache/artifactIdversion1.0.2/version
/dependency
dependencygroupIdnet.sf.ehcache/groupIdartifactIdehcache/artifactIdversion2.10.1/version
/dependencydependencygroupIdorg.slf4j/groupIdartifactIdslf4j-nop/artifactIdversion1.7.2/version
/dependency去各自的sql映射文件里,开启二级缓存,并把缓存类型指定为EhcacheCache cache typeorg.mybatis.caches.ehcache.EhcacheCache/在资源目录下放置一个缓存配置文件,文件名为: ehcache.xml 内容如下 ?xml version1.0 encodingUTF-8?
ehcache xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:noNamespaceSchemaLocationehcache.xsdupdateChecktrue monitoringautodetectdynamicConfigtruediskStore pathD:\msb\ehcache /defaultCachemaxElementsInMemory1000maxElementsOnDisk10000000eternalfalseoverflowToDisktruetimeToIdleSeconds120timeToLiveSeconds120diskExpiryThreadIntervalSeconds120memoryStoreEvictionPolicyLRU/defaultCache
/ehcache!-- Cache配置· nameCache的唯一标识· maxElementsInMemory内存中最大缓存对象数。· maxElementsOnDisk磁盘中最大缓存对象数若是0表示无穷大。· eternalElement是否永久有效一但设置了timeout将不起作用。· overflowToDisk配置此属性当内存中Element数量达到maxElementsInMemory时Ehcache将会Element写到磁盘中。· timeToIdleSeconds设置Element在失效前的允许闲置时间。仅当element不是永久有效时使用可选属性默认值是0也就是可闲置时间无穷大。· timeToLiveSeconds设置Element在失效前允许存活时间。最大时间介于创建时间和失效时间之间。仅当element不是永久有效时使用默认是0.也就是element存活时间无穷大。· diskExpiryThreadIntervalSeconds磁盘失效线程运行时间间隔默认是120秒。· diskSpoolBufferSizeMB这个参数设置DiskStore磁盘缓存的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。· memoryStoreEvictionPolicy当达到maxElementsInMemory限制时Ehcache将会根据指定的策略去清理内存。默认策略是LRU最近最少使用。你可以设置为FIFO先进先出或是LFU较少使用。 --十一、逆向工程 MyBatis的一个主要的特点就是需要程序员自己编写SQL那么如果表太多的话难免会很麻烦所以MyBatis官方提供了一个逆向工程可以针对单表自动生成MyBatis执行所需要的代码包括mapper.xmlmapper.javapojo。一般在开发中常用的逆向工程方式是通过数据库的表生成代码。 dependencies!-- mysql驱动包 --dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion8.0.16/version/dependency!-- 日志包方便查看执行信息--dependencygroupIdorg.slf4j/groupIdartifactIdslf4j-log4j12/artifactIdversion1.6.1/version/dependency!-- 代码生成工具jar --dependencygroupIdorg.mybatis.generator/groupIdartifactIdmybatis-generator-core/artifactIdversion1.3.2/version/dependency
/dependencies配置逆向工程配置文件 在resources目录下放置一个名为generatorConfig.xml的配置文件,文件内容如下 ?xml version1.0 encodingUTF-8?
!DOCTYPE generatorConfigurationPUBLIC -//mybatis.org//DTD MyBatis Generator Configuration 1.0//ENhttp://mybatis.org/dtd/mybatis-generator-config_1_0.dtdgeneratorConfigurationcontext idtestTables targetRuntimeMyBatis3commentGenerator!-- 是否去除自动生成的注释 true是 false:否 --property namesuppressAllComments valuetrue //commentGenerator!--数据库连接的信息驱动类、连接地址、用户名、密码 --!-- jdbcConnection driverClasscom.mysql.jdbc.DriverconnectionURLjdbc:mysql://localhost:3306/mybatis userIdrootpassword密码/jdbcConnection --jdbcConnection driverClasscom.mysql.cj.jdbc.DriverconnectionURLjdbc:mysql://127.0.0.1:3306/mydb?useSSLfalseamp;useUnicodetrueamp;characterEncodingUTF-8amp;serverTimezoneAsia/Shanghaiamp;allowPublicKeyRetrievaltrueuserIdrootpassword密码/jdbcConnection !-- 默认false把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer为 true时把JDBC DECIMAL 和 NUMERIC 类型解析为java.math.BigDecimal --javaTypeResolverproperty nameforceBigDecimals valuefalse //javaTypeResolver!-- targetProject:生成PO类的位置 --javaModelGenerator targetPackagecom.msb.pojotargetProject.\src!-- enableSubPackages:是否让schema作为包的后缀 --property nameenableSubPackages valuefalse /!-- 从数据库返回的值被清理前后的空格 --property nametrimStrings valuetrue //javaModelGenerator!-- targetProject:mapper映射文件生成的位置 --sqlMapGenerator targetPackagecom.msb.mappertargetProject.\src!-- enableSubPackages:是否让schema作为包的后缀 --property nameenableSubPackages valuefalse //sqlMapGenerator!-- targetPackagemapper接口生成的位置 --javaClientGenerator typeXMLMAPPERtargetPackagecom.msb.mappertargetProject.\src!-- enableSubPackages:是否让schema作为包的后缀 --property nameenableSubPackages valuefalse //javaClientGenerator!-- 指定数据库表 --table tableNamedept domainObjectNameDeptenableCountByExamplefalse enableUpdateByExamplefalse enableDeleteByExamplefalse enableSelectByExamplefalse selectByExampleQueryIdfalse columnOverride columnid javaTypeInteger //table/context
/generatorConfiguration 在resources目录下放置一个名为log4j.properties的配置文件,文件内容如下 log4j.rootLoggerdebug,stdoutlog4j.appender.stdoutorg.apache.log4j.ConsoleAppender
log4j.appender.stdout.TargetSystem.err
log4j.appender.stdout.layoutorg.apache.log4j.SimpleLayoutlog4j.appender.logfileorg.apache.log4j.FileAppender
log4j.appender.logfile.Filed:/msb.log
log4j.appender.logfile.layoutorg.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern%d{yyyy-MM-dd HH:mm:ss} %l %F %p %m%n运行逆向工程代码
package com.msb.gennerator;import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;import java.io.File;
import java.util.ArrayList;
import java.util.List;/*** auther:bingwoo*/
public class GeneratorSqlmap {public void generator() throws Exception{ListString warnings new ArrayListString();boolean overwrite true;File configFile new File(D:\\ideaProjects\\reverse\\target\\classes\\generatorConfig.xml);ConfigurationParser cp new ConfigurationParser(warnings);Configuration config cp.parseConfiguration(configFile);DefaultShellCallback callback new DefaultShellCallback(overwrite);MyBatisGenerator myBatisGenerator new MyBatisGenerator(config,callback, warnings);myBatisGenerator.generate(null);}public static void main(String[] args) throws Exception {try {GeneratorSqlmap generatorSqlmap new GeneratorSqlmap();generatorSqlmap.generator();} catch (Exception e) {e.printStackTrace();}}
}十二、main目录下XML文件编译问题
build!--告诉maven将项目源码中的xml文件也进行编译并放到编译目录中--resourcesresourcedirectorysrc/main/java/directoryincludesinclude**/*.xml/include/includesfilteringtrue/filtering/resourceresourcedirectorysrc/main/resources/directoryfilteringtrue/filtering/resource/resources
/build总结
以上是整理的 Mybatis 文章