1)MyBatis是Apache的一个开源项目iBatis, 2010年6月这个项目由Apache Software Foundation 迁移到了Google Code,随着开发团队转投Google Code旗下, iBatis3.x 正式改名为MyBatis ,代码于2013年11月迁移到Githubjava
2)iBatis一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。 iBatis 提供的持久层框架包括SQL Maps和Data Access Objects(DAO)mysql
下载网址git
https://github.com/mybatis/mybatis-3/github
2.Hibernate和JPAsql
3.MyBatis数据库
1.导入MyBatis框架的jar包、Mysql驱动包、log4j的jar包apache
2.导入log4j.xml配置文件编程
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender"> <param name="Encoding" value="UTF-8" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n" /> </layout> </appender> <logger name="java.sql"> <level value="debug" /> </logger> <logger name="org.apache.ibatis"> <level value="info" /> </logger> <root> <level value="debug" /> <appender-ref ref="STDOUT" /> </root> </log4j:configuration>
3.建立测试表api
-- 建立库 CREATE DATABASE test_mybatis; -- 使用库 USE test_mybatis; -- 建立表 CREATE TABLE tbl_employee( id INT(11) PRIMARY KEY AUTO_INCREMENT, last_name VARCHAR(50), email VARCHAR(50), gender CHAR(1) );
4.建立javaBean数组
public class Employee { private Integer id ; private String lastName; private String email ; private String gender ; public Integer getId() { return id; } //...生成get、set 、toString }
5.建立myBatis全局配置文件 (参考官网手册)
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- 数据库链接环境的配置 --> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/mybatis_1129" /> <property name="username" value="root" /> <property name="password" value="123456" /> </dataSource> </environment> </environments> <!-- 引入SQL映射文件,Mapper映射文件 --> <mappers> <mapper resource="EmployeeMapper.xml" /> </mappers> </configuration>
6.建立Mybatis的Mapper映射文件
<?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="suibian"> <select id="selectEmployee" resultType="com.hbuas.myabtis.helloWorld.Employee"> select id ,last_name lastName ,email ,gender from tbl_employee where id = #{id} <!-- select * from tbl_employee where id = #{id} --> </select> </mapper>
7.编写测试类
@Test public void test() throws Exception { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); System.out.println(sqlSessionFactory); SqlSession session = sqlSessionFactory.openSession(); try { Employee employee = session.selectOne("suibian.selectEmployee", 1001); System.out.println(employee); } finally { session.close(); } }
使用mapper接口开发是秉承Mybatis倡导的面向接口编程
1.编写Mapper接口,实现两个绑定:
public interface EmployeeMapper { public Employee getEmployeeById(Integer id ); }
3.编写测试类
获取Mybatis操做数据库的会话对象SqlSession,经过getMapper()获取接口的动态代理实现类
@Test public void test() throws Exception{ String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder() .build(inputStream); SqlSession session = sqlSessionFactory.openSession(); try { //Mapper接口:获取Mapper接口的 代理实现类对象 EmployeeMapper mapper = session.getMapper(EmployeeMapper.class); Employee employee = mapper.getEmployeeById(1006); System.out.println(employee); } finally { session.close(); } }
MyBatis 的配置文件包含了影响 MyBatis 行为甚深的设置(settings)和属性(properties)信息。
配置文件结构以下:
configuration 配置 |
属性信息严格按照上面顺序配置。
<properties> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/test_mybatis" /> <property name="username" value="root" /> <property name="password" value="1234" /> </properties>
properties的做用并不仅仅是这样,你能够建立一个资源文件,名为jdbc.properties的文件,将四个链接字符串的数据在资源文件中经过键值 对(key=value)的方式放置,不要任何符号,一条占一行
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/mybatis_1129 jdbc.username=root jdbc.password=1234
<!-- properties: 引入外部的属性文件 resource: 从类路径下引入属性文件 url: 引入网络路径或者是磁盘路径下的属性文件 --> <properties resource="db.properties" ></properties>
<environments default="oracle"> <environment id="mysql"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </dataSource> </environment> </environments>
<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>
1.类型别名是为 Java 类型设置一个短的名字,能够方便咱们引用某个类。
<typeAliases> <typeAlias type="com.hbuas.mybatis.beans.Employee" alias="emp"/> </typeAliases>
alias属性能够不写,不写默认就是类名切不区分大小写。
2.类不少的状况下,能够批量设置别名这个包下的每个类建立一个默认的别名,就是简单类名小写
<typeAliases> <package name="com.hbuas.mybatis.beans"/> </typeAliases>
<environments default="oracle"> <environment id="mysql"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </dataSource> </environment> <environment id="oracle"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${orcl.driver}" /> <property name="url" value="${orcl.url}" /> <property name="username" value="${orcl.username}" /> <property name="password" value="${orcl.password}" /> </dataSource> </environment> </environments>
cache – 给定命名空间的缓存配置。
cache-ref – 其余命名空间缓存配置的引用。
resultMap – 是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加载对象。
parameterMap – 已废弃!老式风格的参数映射。内联参数是首选,这个元素可能在未来被移除,这里不会记录。
sql – 可被其余语句引用的可重用语句块。
insert – 映射插入语句
update – 映射更新语句
delete – 映射删除语句
select – 映射查询语
public interface EmpMapper { //根据eid查询一个员工信息 Emp getEmpByEid(String eid); //获取全部的员工信息 List<Emp> getAllEmp(); //添加员工信息 void addEmp(Emp emp); //修改员工信息 void updateEmp(Emp emp); //删除员工信息 Boolean deleteEmp(String eid); }
<mapper namespace="com.hbuas.mapper.EmpMapper"> <!-- Emp getEmpByEid(String eid); --> <select id="getEmpByEid" resultType="Emp"> select eid,ename,age,sex from emp where eid = #{eid} </select> <!-- List<Emp> getAllEmp(); --> <select id="getAllEmp" resultType="Emp"> select eid,ename,age,sex from emp </select> <!-- void addEmp(Emp emp); --> <insert id="addEmp"> insert into emp values(null,#{ename},#{age},#{sex}) </insert> <!-- void updateEmp(Emp emp); --> <update id="updateEmp"> update emp set ename = #{ename}, age = #{age}, sex = #{sex} where eid = #{eid} </update> <!-- void deleteEmp(String eid); --> <delete id="deleteEmp"> delete from emp where eid = #{eid} </delete> </mapper>
<insert id="insertEmployee" parameterType="com.hbuas.mybatis.beans.Employee" databaseId="mysql" useGeneratedKeys="true" keyProperty="id"> insert into tbl_employee(last_name,email,gender) values(#{lastName},#{email},#{gender}) </insert>
<insert id="insertEmployee" parameterType="com.atguigu.mybatis.beans.Employee" databaseId="oracle"> <selectKey order="BEFORE" keyProperty="id" resultType="integer"> select employee_seq.nextval from dual </selectKey> insert into orcl_employee(id,last_name,email,gender) values(#{id},#{lastName},#{email},#{gender}) </insert>
myBatis获取参数值的两种方式:
1.单个普通类型参数:能够接受基本类型,包装类型,字符串类型等。
2.多个参数
任意多个参数,都会被MyBatis从新包装成一个Map传入。Map的key是param1,param2,或者0,1…,值就是参数的值
#{}:#{0}、#{1}、#{param1}、#{param2}
${}:${value}、${ param2 },可是要注意${}的单引号问题
3.命名参数
为参数使用@Param起一个名字,MyBatis就会将这些参数封装进map中,key就是咱们本身指定的名字。#{},${}均可以经过健名获取值,注意单引号问题。
4.POJO
当这些参数属于咱们业务POJO时,咱们直接传递POJO属性名获取值,可是注意${}单引号问题。
5.Map
咱们也能够封装多个参数为map,直接传递
6.Collection/Array
会被MyBatis封装成一个map传入, List以list为键,Array以array为键
<!-- <resultMap>:自定义映射,处理复杂的表关系 <id column="eid" property="eid"/> <id>:设置主键的映射关系,column设置字段名,property设置属性名 <result column="ename" property="ename"/> <result>:设置非主键的映射关系,column设置字段名,property设置属性名 -->
<!-- 此种方式用的比较少--> <resultMap type="Emp" id="empMap"> <id column="eid" property="eid"/> <result column="ename" property="ename"/> <result column="age" property="age"/> <result column="sex" property="sex"/> <result column="did" property="dept.did"/> <result column="dname" property="dept.dname"/> </resultMap> <!-- List<Emp> getAllEmp(); --> <select id="getAllEmp" resultMap="empMap"> select e.eid,e.ename,e.age,e.sex,e.did,d.dname from emp e left join dept d on e.did = d.did </select>
以级联属性的方式封装对象.
<resultMap type="Emp" id="empMap"> <id column="eid" property="eid"/> <result column="ename" property="ename"/> <result column="age" property="age"/> <result column="sex" property="sex"/> <association property="dept" javaType="Dept"> <id column="did" property="did"/> <result column="dname" property="dname"/> </association> </resultMap>
<select id="getEmployeeAndDeptStep" resultMap="myEmpAndDeptStep"> select id, last_name, email,gender,d_id from tbl_employee where id =#{id} </select> <resultMap type="com.hbuas.mybatis.beans.Employee" id="myEmpAndDeptStep"> <id column="id" property="id" /> <result column="last_name" property="lastName"/> <result column="email" property="email"/> <result column="gender" property="gender"/> <association property="dept" select="com.hbuas.mybatis.dao.DepartmentMapper.getDeptById" column="d_id" fetchType="eager"> </association> </resultMap>
Settings中进行以下的配置:
<!-- 开启延迟加载 --> <setting name="lazyLoadingEnabled" value="true"/> <!-- 设置加载的数据是按需仍是所有 --> <setting name="aggressiveLazyLoading" value="false"/>
专门用来处理一对多和多对多的关系
<resultMap type="Dept" id="deptMap"> <id column="did" property="did"/> <result column="dname" property="dname"/> <!-- <collection>:处理一对多和多对多的关系 ofType:指集合中的类型,不须要指定javaType --> <collection property="emps" ofType="Emp"> <id column="eid" property="eid"/> <result column="ename" property="ename"/> <result column="age" property="age"/> <result column="sex" property="sex"/> </collection> </resultMap>
对于查询部门信息而且将对应的全部的员工信息也查询出来的需求,就能够经过分步的方式完成查询。
<!-- List<Emp> getEmpListByDid(String did); --> <select id="getEmpListByDid" resultType="Emp"> select eid,ename,age,sex from emp where did = #{did} </select> <resultMap type="Dept" id="deptMapStep"> <id column="did" property="did"/> <result column="dname" property="dname"/> <collection property="emps" select="com.hbuas.mapper.EmpDeptMapper.getEmpListByDid" column="{did=did}" fetchType="eager"></collection> </resultMap> <!-- Dept getOnlyDeptByDid(String did); --> <select id="getOnlyDeptByDid" resultMap="deptMapStep"> select did,dname from dept where did = #{did} </select>
1.在<association> 和<collection>标签中均可以设置fetchType,指定本次查询是否要使用延迟加载。默认为 fetchType=”lazy” ,若是本次的查询不想使用延迟加载,则可设置为fetchType=”eager”.
2.fetchType能够灵活的设置查询是否须要使用延迟加载,而不须要由于某个查询不想使用延迟加载将全局的延迟加载设置关闭.
MyBatis动态SQL简介
<select id="getEmpListByMoreTJ1" resultType="Emp"> select eid,ename,age,sex,did from emp <where> <if test="eid != null"> and eid = #{eid} </if> <if test="ename != null and ename != ''"> and ename = #{ename} </if> <if test="age != null"> and age = #{age} </if> <if test="sex == 1 or sex == 0"> and sex = #{sex} </if> </where> </select>
<select id="getEmpListByMoreTJ1" resultType="Emp"> select eid,ename,age,sex,did from emp <trim prefix="where" suffixOverrides="and"> <if test="eid != null"> eid = #{eid} and </if> <if test="ename != null and ename != ''"> ename = #{ename}and </if> <if test="age != null"> age = #{age}and </if> <if test="sex == 1 or sex == 0"> sex = #{sex} </if> </where> </select>
set 主要是用于解决修改操做中SQL语句中可能多出逗号的问题
<update id="updateEmpByConditionSet"> update tbl_employee <set> <if test="lastName!=null && lastName!="""> last_name = #{lastName}, </if> <if test="email!=null and email.trim()!=''"> email = #{email} , </if> <if test=""m".equals(gender) or "f".equals(gender)"> gender = #{gender} </if> </set> where id =#{id} </update>
choose 主要是用于分支判断,相似于java中的switch case,只会知足全部分支中的一个
<select id="getEmpsByConditionChoose" resultType="com.hbuas.mybatis.beans.Employee"> select id ,last_name, email,gender from tbl_employee <where> <choose> <when test="id!=null"> id = #{id} </when> <when test="lastName!=null"> last_name = #{lastName} </when> <when test="email!=null"> email = #{email} </when> <otherwise> gender = 'm' </otherwise> </choose> </where> </select>
<!-- <foreach collection="" item="" close="" open="" separator="" index=""></foreach> 对一个数组或集合进行遍历 collection:指定要遍历的集合或数组 item:设置别名 close:设置循环体的结束内容 open:设置循环体的开始内容 separator:设置每一次循环之间的分隔符 index:若遍历的是list,index表明下标;若遍历的是map,index表明键 -->
<delete id="deleteMoreByList"> delete from emp where eid in <foreach collection="eids" item="eid" separator="," open="(" close=")"> #{eid} </foreach> </delete>
sql 标签是用于抽取可重用的sql片断,将相同的,使用频繁的SQL片断抽取出来,单独定义,方便屡次引用.
<!-- <sql id=""></sql>:设置一段SQL片断,即公共SQL,能够被当前映射文件中全部的SQL语句所访问 <include refid="empColumns"></include>:访问某个SQL片断 --> <sql id="empColumns">select eid,ename,age,sex,did from emp </sql> <select id="getEmpByEid" resultType="Emp"> <include refid="empColumns"></include> where eid = #{eid} </select>
MyBatis 包含一个很是强大的查询缓存特性,它能够很是方便地配置和定制。缓存能够极大的提高查询效率,MyBatis系统中默认定义了两级缓存(一级缓存、二级缓存)默认状况下,只有一级缓存(SqlSession级别的缓存,也称为本地缓存)开启。
/** mybatis中的一级缓存默认开启,是SqlSession级别的 即同一个SqlSession对于一个sql语句,执行以后就会存储在缓存中,下次执行相同的sql,直接从缓存中取 一级缓存失效的状况: * 不一样的SqlSession对应不一样的一级缓存 * 同一个SqlSession可是查询条件不一样 * 同一个SqlSession两次查询期间执行了任何一次增删改操做,会自动将缓存清空 * 同一个SqlSession两次查询期间手动清空了缓存 */
/** * mybatis的二级缓存默认不开启,须要设置: * 一、在核心配置文件<settings>中,加入配置:<setting name="cacheEnabled" value="true"/> * 二、须要使用二级缓存的映射文件处使用cache配置缓存<cache /> * 三、注意:POJO须要实现Serializable接口 * 注意:二级缓存在 SqlSession 关闭或提交以后才会生效 * 1)全局setting的cacheEnable: 配置二级缓存的开关,一级缓存一直是打开的 * 2)select标签的useCache属性: 配置这个select是否使用二级缓存。一级缓存一直是使用的 * 3)sql标签的flushCache属性: 增删改默认flushCache=true。sql执行之后,会同时清空一级和二级缓存。 查询默认 flushCache=false。 * 4)sqlSession.clearCache():只是用来清除一级缓存 */
二级缓存相关的属性
LRU – 最近最少使用的:移除最长时间不被使用的对象。
FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
默认的是 LRU。
默认状况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新
表明缓存最多能够存储多少个对象,太大容易致使内存溢出
true:只读缓存;会给全部调用者返回缓存对象的相同实例。所以这些对象不能被修改。这提供了很重要的性能优点。
false:读写缓存;会返回缓存对象的拷贝(经过序列化)。这会慢一些,可是安全,所以默认是 false。
为了提升扩展性。MyBatis定义了缓存接口Cache。咱们能够经过实现Cache接口来自定义二级缓存
EhCache 是一个纯Java的进程内缓存框架,具备快速、精干等特色,是Hibernate中默认的CacheProvider
整合EhCache缓存的步骤
1.导入ehcache包,以及整合包,日志包
2.编写ehcache.xml配置文件
<?xml version="1.0" encoding="UTF-8"?> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"> <!-- 磁盘保存路径 --> <diskStore path="D:\hbuas\ehcache" /> <defaultCache maxElementsInMemory="1000" maxElementsOnDisk="10000000" eternal="false" overflowToDisk="true" timeToIdleSeconds="120" timeToLiveSeconds="120" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU"> </defaultCache> </ehcache> <!-- 属性说明: l diskStore:指定数据在磁盘中的存储位置。 l defaultCache:当借助CacheManager.add("demoCache")建立Cache时,EhCache便会采用<defalutCache/>指定的的管理策略 如下属性是必须的: l maxElementsInMemory - 在内存中缓存的element的最大数目 l maxElementsOnDisk - 在磁盘上缓存的element的最大数目,如果0表示无穷大 l eternal - 设定缓存的elements是否永远不过时。若是为true,则缓存的数据始终有效,若是为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断 l overflowToDisk - 设定当内存缓存溢出的时候是否将过时的element缓存到磁盘上 如下属性是可选的: l timeToIdleSeconds - 当缓存在EhCache中的数据先后两次访问的时间超过timeToIdleSeconds的属性取值时,这些数据便会删除,默认值是0,也就是可闲置时间无穷大 l timeToLiveSeconds - 缓存element的有效生命期,默认是0.,也就是element存活时间无穷大 diskSpoolBufferSizeMB 这个参数设置DiskStore(磁盘缓存)的缓存区大小.默认是30MB.每一个Cache都应该有本身的一个缓冲区. l diskPersistent - 在VM重启的时候是否启用磁盘保存EhCache中的数据,默认是false。 l diskExpiryThreadIntervalSeconds - 磁盘缓存的清理线程运行间隔,默认是120秒。每一个120s,相应的线程会进行一次EhCache中数据的清理工做 l memoryStoreEvictionPolicy - 当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出) -->
3.配置cache标签
<cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>