头图: www.zcool.com.cn/work/ZNTE1M…html
框架的好处java
框架是一个半成品,已经对基础的代码进行了封装并提供相应的 API,开发者在 使用框架是直接调用封装好的 API 能够省去不少代码编写,从而提升工做效率和开发速度mysql
学习目标git
掌握:程序员
Mybatis的基本使用、Java 日志处理框架、Mybatis 配置完善 、SqlSession 经常使用 API 、Mapper 动态代理 、动态 SQL 、Mybatis 缓存 、Mybatis 多表关联查询、Mybatis 注解的使用 、Mybatis Generator 工具的使用、PageHelper 分页插件、Mybatis 与 Servlet 整合web
MyBatis框架的优势和缺点算法
对象关系映射,它的做用是在关系型数据库和对象之间做一个映射处理。项目中的业务实体有两种表现形式:对象和关系数据,即在内存中表现为对象,在数据库中表现为关系数据。spring
JDBC 的缺点:须要手动的完成面向对象的 Java 语言、面向关系的数据库之间数据的转换,代码繁琐,影响了开发效率。sql
ORM:在面向对象的java语言中,面向关系的数据库之间数据的转换是必须的,数据库中的数据是不能直接拿来使用,须要转换成须要的对象来使用,可是每次在开发时须要先创建数据库而后在对数据库中的数据转成咱们能够操做的对象;所以ORM就至关于转换的桥梁,开发者不须要和sql语句打交道了。数据库
ORM将数据库映射成对象
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎全部的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain OrdinaryJava Object,普通的 Java 对象)映射成数据库中的记录。MyBatis是一个半自动ORM框架,其本质是对JDBC的封装。使用MyBatis重点须要程序员编写 SQL 命令,不须要写一行 JDBC 代码。
持久层框架:优化了对数据库的访问速度,减小了对数据库中的访问频率,将数据库中的关系数据经过对象关系映射成对象,这时对象中的存放的就是数据库中的内容(若是须要执行则存放到内存中),当程序须要某一个对象的属性执行时,无需再从数据库中访问且作转换就能够获取。
与 Hibernate 的比较:
Hibernate 是一个全自动的 ORM 框架。由于 Hibernate 建立了 Java 对象和数据库表之间的完整映射,能够彻底以面向对象的思想来操做数据库,程序员不须要手写 SQL 语句。而 MyBatis 中还须要手写 SQL 语句,因此是半自动化的,工做量要大于 Hibernate。为何半自动化的 Mybatis 自动化的 Hibernate 受欢迎?
MyBatis 须要手写 SQL 语句,因此工做量要大于 Hibernate。可是也正是因为自定义SQL 语句,因此其灵活性、可优化性就超过了 Hibernate。MyBatis 将手写 SQL 语句的工做丢给开发者,能够更加精确的定义 SQL,更加灵活, 也便于优化性能。完成一样功能的两条 SQL 语句的性能可能相差十几倍到几十倍,在高并发、快响应要求下的互联网系统中,对性能的影响更明显。MyBatis 对存储过程可提供很好的支持。
SqlSessionFactoryBuilder
SqlSessionFactoryBuilder的做用是用来建立 SqlSessionFactory 对象。当 SqlSessionFactory 对象被建立后,SqlSessionFactoryBuilder 就失去了做用,因此它只能存在于建立 SqlSessionFactory 的方法中,而不要让其长期存在。所以 SqlSessionFactoryBuilder 实例的最佳做用域是方法做用域。
SqlSessionFactory
能够被认为是一个数据库链接池,它的做用是建立 SqlSession接口对象。一旦建立了SqlSessionFactory,就要长期保存它,直至再也不使用 MyBatis 应用,因此能够认为SqlSessionFactory 的生命周期就等同于 MyBatis 的应用周期。因为 SqlSessionFactory是 一 个 对 数 据 库 的 连 接 池 , 所 以 它 占 据 着 数 据 库 的 连 接 资 源 。 如 果 创 建 多 个SqlSessionFactory,那么就存在多个数据库链接池,这样不利于对数据库资源的控制,也会致使数据库链接资源被消耗光,出现系统宕机等状况,因此尽可能避免发生这样的状况。所以 SqlSessionFactory 是一个单例,让它在应用中被共享。
SqlSession
若是说 SqlSessionFactory 至关于数据库链接池,那么 SqlSession 就至关于一个数据库链接(Connection 对象),你能够在一个事务里面执行多条 SQL,而后经过它的commit、rollback 方法提交或者回滚事务。SqlSession 应该存活在一个业务请求中,处理完整个请求后,应该关闭这条链接,让它归还给 SqlSessionFactory,不然数据库资源就很快被耗费精光,系统就会瘫痪,因此用 try...catch...finally... 语句来保证其正确关闭
Mapper
映射器。由一个 Java 接口和 XML 文件(或者注解构成),须要给出对应的 SQL 和映射规则,负责发送 SQL 去执行并返回结果。因为 SqlSession 的关闭,它的数据库链接资源也会消失,因此它的生命周期应该小于等于 SqlSession 的生命周期。Mapper 表明的是一个请求中的业务处理,因此它应该在一个请求中,一旦处理完了相关的业务,就应该废弃它。
全局配置文件和映射配置文件:若是说全局配置闻不见是链接数据库的配置已经环境的设置,那么映射配置文件就是编写sql语句的(JDBC是将sql语句和代码写在一块儿而后进行CRUD,Mybatis则是进行了节偶,是功能代码具备可用性,开发简单。
全局配置文件的名称是自定义的,在 JavaProject 项目中须要放到 src 目录下。全局配置文件的做用是完成一些全局性的配置,如:对 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>
</configuration>
复制代码
properties 标签中容许内部定义属性,也能够是外部的properties 文件定义属性。不管是内部定义仍是外部定义,均可以使用${name}获取值。
配置文件中内部定义
<properties>
<property name="jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="jdbc.url" value="jdbc:mysql://localhost:3306/bjsxt"/>
<property name="jdbc.username" value="root"/>
<property name="jdbc.password" value="root"/>
</properties>
复制代码
配置文件中外部定义
<properties resource="db.properties"></properties>
复制代码
setting 标签的配置是配置 MyBatis 框架运行时的一些行为的,例如缓存、延迟加载、结果集控制、执行器、分页设置、命名规则等一系列控制性参数,其全部的 setting 配置都放在父标签 settings 标签中(也能够不用配置)。
<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>
复制代码
类型别名可为 Java 类型设置一个缩写名字。
<typeAliases>
<typeAlias alias="user" type="com.bjsxt.pojo.User" />
</typeAliases>
复制代码
也能够指定一个包名,MyBatis 会在包名下面搜索须要的 Java Bean
<typeAliases>
<package name="com.bjsxt.pojo"/>
</typeAliases>
复制代码
配置链接数据库的环境,能够配置多个环境,好比:开发、测试、发布产品的环境
<environments default="development">
<environment id="development">
<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>
复制代码
transactionManager 节点
事务处理器。在Mybatis中有两种事务管理器,也就是type = JDBC或type = MANAGED
JDBC:这个配置直接使用了 JDBC 的提交和回滚事务,它依赖从数据源得到的链接来管理事务做用域
MANAGED:在Mybatis中不作事务处理,在JavaEE开发的标准中根据开发框架获取事务
配置数据链接源(JDBC链接对象的资源,获取数据链接池)
指定映射配置文件
使用相对类路径指定映射配置文件
<mappers>
<mapper resource="com/bjsxt/mapper/UserMapper.xml"/>
</mappers>
复制代码
使用 filter:///协议指定映射配置文件
<mappers>
<mapper url="file:///D:\code\mybatis\src\com\bjsxt\mapper\UserMapper.xml"/>
</mappers>
复制代码
指定映射接口
<mappers>
<mapper class="com.bjsxt.mapper.UserMapper"/>
</mappers>
复制代码
经过包名指定映射接口(指定映射文件)
<mappers>
<package name="com.bjsxt.mapper"/>
</mappers>
复制代码
映射配置文件主要是用来编写 sql 语句的,结果集的映射关系的指定,以及缓存的一些配置等等。
<?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="com.bjsxt.mapper.UserMapper">
</mapper>
复制代码
mybatis中能够为每一个映射文件起一个惟一的命名空间(namespace),只要这个命名空间的id是惟一,即便不一样的映射文件的sql语句id同样也不会产生冲突
<resultMap id="userMapper" type="com.bjsxt.pojo.User">
<id property="userid" column="user_id"/>
<result property="username" column="user_name"/>
</resultMap>
复制代码
指定查询结果集与对象的映射关系的标签
type:类的彻底名, 或者一个类型别名,能够理解为数据库中的表转换成了一个对象,该对象里面的属性即便数据库中表的字段名称,CRUD该表时,将字段对应的数据填充到改对象中。
id:惟一标识。在进行业务处理时,该标签指定程序获取执行sql语句,在一个映射文件中是惟一的
指定主键中的值,用于标识一个结果映射。
property: 该属性值至关于在操做sql语句时起的别名
<select id="selectUser" parameterType="int" resultType="u">
select * from users where userid = #{userid}
</select>
复制代码
parameterType:指定参数类型。该属性是可选属性。由于 MyBatis 能够经过类型处理器(TypeHandler)推断出具体传入语句的参数。
resultType:指望从这条语句中返回结果的类全名或别名。
resultMap:使用 resultMap 标签来处理结果集映射。
在没有联网的状况下,若是让 dtd 约束继续起做用,而且出现标签提示,能够经过引入本地 dtd 文件来实现,将下载的 dtd 拷贝到本地的一个目录下
Idea 操做路径:File---Settings---Languages & Frameworks。其中 URI 复制 dtd 的网络地址便可。File 选择 dtd 文件在本地的地址
注意:在 MyBatis 的核心 jar 包中就提供了 mybatis-3-config.dtd
public class Users {
private int userid;
private String username;
private String usresex;
public int getUserid() {
return userid;
}
public void setUserid(int userid) {
this.userid = userid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getUsresex() {
return usresex;
}
public void setUsresex(String usresex) {
this.usresex = usresex;
}
}
复制代码
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/bjsxt
jdbc.username=root
jdbc.password=root
复制代码
在这里使用了外部定义的properties属性
<?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>
<!-- 引入 properties 文件 -->
<properties resource="db.properties"/>
<!-- 环境的配置 -->
<environments default="development">
<environment id="development">
<!-- 配置事务 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置数据源 -->
<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>
<!-- 引入映射配置文件 -->
<mappers>
<!-- 使用相对路径方式引入,不一样的实体类有不一样的映射配置文件,若是实体类比较多则比较麻烦 -->
<mapper resource="com/bjsxt/mapper/UsersMapper.xml"/>
</mappers>
</configuration>
复制代码
<?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="com.bjsxt.mapper.UserMapper">
<!-- 查询全部用户 -->
<select id="selectUsersAll" resultType="com.bjsxt.pojo.Users">
select * from users
</select>
</mapper>
复制代码
public interface UsersDao {
List<Users> selectUsersAll()throws IOException;
}
复制代码
public class UsersDaoImpl implements UsersDao {
/** * 查询全部用户 * @return */
@Override
public List<Users> selectUsersAll()throws IOException {
// 建立 SqlSessionFactory 对象
InputStream inputStream = Resources.getResourceAsStream("mybatis-cfg.xml");
SqlSessionFactory sqlSessionFacotry = new SqlSessionFactoryBuilder().build(inputStream);
// 获取 SqlSession 对象
SqlSession sqlSession = sqlSessionFacotry.openSession();
// 经过 SqlSession 对象下的 API 完成对数据库的操做
List<Users> list = sqlSession.selectList("com.bjsxt.mapper.UserMapper.selectUsersAll");
// 关闭 SqlSession 对象
sqlSession.close();
return list;
}
}
复制代码
在映射配置文件中向 SQL 语句中绑定参数的语法结构为#{ }和${ }。
#{}和${}的区别(面)
#{ }: 解析为一个 JDBC 预编译语句(PreparedStatement)的参数标记符占位符 ?。使 用该方式可避免 SQL 注入
** { } 在预编译以前已经被变量替换了,这会存在 SQL 注入问题。
ThreadLocal 提供了线程内存储变量的能力,这些变量不一样之处在于每个线程读取的变量是对应的互相独立的。经过 get 和 set 方法就能够获得当前线程对应的值
若是多个 DML 操做属于一个事务,由于 commit()和 rollback()都是由 SqlSession 完成的,因此必须保证使用一个 SqlSession。可是多个不一样的 DML 操做可能在不一样类的不一样方法中,每一个方法中要单独的获取 SqlSession。好比商城下订单时,其实涉及商品库存变化、订单添加、订单明细添加、付款、日志添加等多个 DML 操做,分布在不一样类中。如何在多个 DML 操做之间使用同一个 SqlSession 呢,可使用 ThreadLocal 来存储。保证一个线程中的操做使用的都是一个 SqlSession。
在 Web 项目中用户的每次请求会启动一个新的线程,好比点击”结算”完成购物车结算。在 Java 项目中每次启动 main()也会自动开启一个 main 线程
public class MybatisUtils {
private static ThreadLocal<SqlSession> threadLocal = new ThreadLocal<>();
private static SqlSessionFactory sqlSessionFactory = null;
static{
// 建立 SqlSessionFactory
InputStream is = null;
try{
is = Resources.getResourceAsStream("mybatis-cfg.xml");
}catch (IOException e){
e.printStackTrace();
}
sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
}
// 获取 SqlSession
public static SqlSession getSqlSession(){
SqlSession sqlSession = threadLocal.get();
if(sqlSession == null){
sqlSession = sqlSessionFactory.openSession();
threadLocal.set(sqlSession);
}
return sqlSession;
}
// 关闭 SqlSession
public static void closeSqlSession(){
SqlSession sqlSession = threadLocal.get();
if(sqlSession != null){
sqlSession.close();
threadLocal.set(null);
}
}
}
复制代码
在 Mybatis 中事务提交方式默认为手动提交,这与 JDBC 是不一样的。在 JDBC 中事务默认提交方式为自动提交。
SqlSession sqlSession = sqlSessionFacotry.openSession();
复制代码
SqlSession sqlSession = sqlSessionFacotry.openSession(true);
复制代码
Log4j: Log For Java(Java 的日志) 是 Apache 提供的一个开源的 Java 主流的日志框架。
Log4j2:
Log4j 定义了 8 个日志级别(除去 OFF 和 ALL,能够说分为 6 个级别),优先级从高到 低依次为:OFF、FATAL、ERROR、WARN、INFO、DEBUG、TRACE、 ALL。
在 Log4j 中建议只使用 DEBUG、INFO、WARN、ERROR 四个日志级别
误,这种级别你能够直接中止程序了。
Commons
Logging,
Slf4j,
Logback,
Jul。
Log4j 配置文件名:log4j 配置文件名:log4j.properties,Log4j 配值文件存放位置:项目的 src 的根目录中
配置根 Logger:
log4j.rootLogger = [level],appenderName,appenderName2,...
复制代码
level 是日志记录的优先级,优先级从低到高分别是 DEBUG,INFO,WARN,ERROR。经过在这里定义的级别,您能够控制到应用程序中相应级别的日志信息的开关,好比在这里定义了INFO 级别,则应用程序中全部 DEBUG 级别的日志信息将不被打印出来appenderName 就是指定日志信息输出到哪一个地方。可同时指定多个输出目的地。
Log4j 中的 appender
org.apache.log4j.ConsoleAppender(输出到控制台) org.apache.log4j.FileAppender(输出到文件) org.apache.log4j.DailyRollingFileAppender(天天产生一个日志文件) org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件) org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方) org.apache.log4j.jdbc.JDBCAppender(将日志信息添加数据库中)
向控制台输出的 appender
# appender.console 输出到控制台
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=<%d> %5p (%F:%L) [%t] (%c)- %m%n
log4j.appender.console.Target=System.out
复制代码
向文件输出的 appender
### appender.logfile 输出到日志文件 ###
log4j.appender.logfile=org.apache.log4j.RollingFileAppender
log4j.appender.logfile.File=SysLog.log
log4j.appender.logfile.MaxFileSize=500KB
log4j.appender.logfile.MaxBackupIndex=7
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=<%d> %p (%F:%L) [%t] %c - %m%n
复制代码
向数据库输出的 appender
log4j.appender.logDB=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.logDB.layout=org.apache.log4j.PatternLayout
log4j.appender.logDB.Driver=com.mysql.jdbc.Driver
log4j.appender.logDB.URL=jdbc:mysql://localhost:3306/bjsxt
log4j.appender.logDB.User=root
log4j.appender.logDB.Password=root
log4j.appender.logDB.Sql=INSERT INTO
logs(project_name,create_date,level,category,file_name,thread_name,line,all_
category,message)values('logDemo','%d{yyyy-MM-ddHH:mm:ss}','%p','%c','%F','%t','%L','%l','%m')
复制代码
经过包名控制日志输出级别
log4j.logger.org.apache=FATAL
log4j.logger.org.apache.commons=ERROR
log4j.logger.org.springframework=ERROR
log4j.logger.com.bjsxt=ERROR
复制代码
规范
在映射文件中,SQL 语句中的参数须要使用 arg0,arg1...或者 param1,param2...表示参数的顺序。此方法可读性低,且要求参数的顺序不能出错,在开发中不建议使用
List selectUsersOrderParam(String username,String usersex); |
---|
select * from users where username = #{arg0} and usersex= #{arg1} |
select * from users where username = #{param1} and usersex=#{param2} |
在接口方法的参数列表中经过@Param 注解来定义参数名称,在 SQL 语句中经过注解中所定义的参数名称完成参数位置的指定。 此方式在参数很少的状况仍是比较直观的,推荐使用。
<!-- 根据用户姓名与性别查询用户 , 使用 @Param 注解传参法 -->
<select id="selectUsersAnnParam" resultType="users">
select * from users where username = #{name} and usersex= #{sex}
</select>
复制代码
List<Users> selectUsersAnnParam(@Param("name") String username,@Param("sex") String usersex);
复制代码
在 Mapper 动态代理中也可使用 POJO 做为传递参数的载体,在 SQL 语句中绑定参数时使用 POJO 的属性名做为参数名便可。此方式推荐使用。
<!-- 根据用户姓名与性别查询用户 , 使用 POJO 传参法 -->
<select id="selectUsersPOJOParam" resultType="users">
select * from users where username = #{username} and usersex=#{usersex}
</select>
复制代码
List<Users> selectUsersPOJOParam(Users users);
复制代码
在 Mapper 动态代理中也可使用 Map 做为传递参数的载体,在 SQL 语句中绑定参数时使用 Map 的 Key 做为参数名便可。此方法适合在传递多参数时,若是没有 POJO 能与参数匹配,可使用该方式传递参数。推荐使用。
MyBatis 传递 map 参数时,若是传递参数中没有对应的 key 值,在执行 sql 语句时默认取的是 null。
<!-- 根据用户姓名与性别查询用户 , 使用 Map 传参法 -->
<select id="selectUsersMapParam" resultType="users">
select * from users where username = #{keyname} and usersex=#{keysex}
</select>
复制代码
List<Users> selectUsersMapParam(Map<String,String> map);
复制代码
咱们可使用符号的实体来表示
<select id="selectUsers" resultType="users">
select * from users where userid > #{userid}
</select>
复制代码
Mybatis动态sql有什么用?执行原理?有哪些动态sql?
在 MyBatis 中提供了动态 SQL 功能。将使用 Java 代码拼接 SQL 语句,改变为在 XML 映射文件中使用标签拼接 SQL 语句。
MyBatis 中动态 SQL 是编写在 mapper.xml 中的,其语法和 JSTL 相似,可是倒是基于强大的 OGNL 表达式实现的。
OGNL (对象导航图语言(Object Graph Navigation Language),简称OGNL,是应用于Java中的一个开源的表达式语言(Expression Language),它被集成在Struts2等框架中,做用是对数据进行访问,它拥有类型转换、访问对象方法、操做集合对象等功能。)
if 标签单分支判断语句
<!-- 根据用户给定的条件进行查询 -->
<select id="selectUsersByProperty" resultType="users">
select * from users where 1=1
<if test="userid != 0">
and userid = #{userid}
</if>
<if test="username != null and username != ''">
and username = #{username}
</if>
<if test="usersex != null and usersex != ''">
and usersex = #{usersex}
</if>
</select>
复制代码
从多个条件中选择一个使用。
<!-- 多选一条件 -->
<select id="selectUsersByChoose" resultType="users">
select * from users where 1=1
<choose>
<when test="username != null and username != ''">
and username = #{username}
</when>
<when test="usersex != null and usersex != ''">
and usersex = #{usersex}
</when>
<otherwise>
and userid = 1
</otherwise>
</choose>
</select>
复制代码
使用 where 标签,就不须要提供 where 1=1 这样的条件了。若是判断条件不为空则自动添加 where 关键字,而且会自动去掉第一个条件前面的 and 或 or
<!-- 根据用户给定的条件进行查询使用 where 标签实现 -->
<select id="selectUsersByPropertyWhere" resultType="users">
select * from users
<where>
<if test="userid != 0">
and userid = #{userid}
</if>
<if test="username != null and username != ''">
and username = #{username}
</if>
<if test="usersex != null and usersex != ''">
and usersex = #{usersex}
</if>
</where>
</select>
复制代码
bind 标签容许咱们在 OGNL 表达式之外建立一个变量,并能够将其绑定到当前的 SQL语句中。通常应用于模糊查询,经过 bind 绑定通配符和查询值。
<!-- 根据用户姓名模糊查询 -->
<select id="selectUsersByLikeName" resultType="users">
<bind name="likeName" value="'%'+name+'%'"/>
select * from users where username like #{likeName}
</select>
复制代码
set 标签用在 update 语句中。借助 if 标签,能够只对有具体值的字段进行更新。set 标签会自动添加 set 关键字,自动去掉最后一个 if 语句的多余的逗号。
<!-- 选择更新 -->
<update id="usersUpdate">
update users
<set>
<if test="username != null and username != ''">
username = #{username},
</if>
<if test="usersex != null and usersex != ''">
usersex = #{usersex},
</if>
</set>
where userid = #{userid}
</update>
复制代码
foreach 标签的功能很是强大,咱们能够将任何可迭代对象如 List、Set 、Map 或者数组对象做为集合参数传递给 foreach 标签进行遍历。它也容许咱们指定开头与结尾的字符串以及集合项迭代之间的分隔符。
迭代 List、Set
<!-- 查询用户 ID 为 1 或者 2 的用户 -->
<select id="selectUsersByIdUseCollection" resultType="users">
select * from users where userid in
<foreach collection="collection" item="userid" open="(" separator="," close=")">
#{userid}
</foreach>
</select>
复制代码
迭代数组
<!-- 查询用户 ID 为 1 或者 2 的用户使用数组传递参数 -->
<select id="selectUsersByIdUseArray" resultType="users">
select * from users where userid in
<foreach collection="array" item="userid" open="(" separator="," close=")">
#{userid}
</foreach>
</select>
复制代码
在执行了一次SQL查询语句时,查询结果存储在内存或者某种缓存介质(Mybatis的缓存介质有哪些)当中,当下次遇到相同的查询 SQL 时候不在执行该 SQL,而是直接从缓存中获取结果
MyBatis 缓存方式分为一级缓存和二级缓存,同时也可配置关于缓存设置。
一级缓存是将结果缓存在 SqlSession 对象中,二级缓存是存储在 SqlSessionFactory 对象中。默认状况下,MyBatis 开启一级缓存,没有开启二级缓存。当数据量大的时候能够借助一些第三方缓存技术来协助保存 Mybatis 的二级缓存数据。
一级缓存也叫本地缓存,MyBatis 的一级缓存是在会话(SqlSession)层面进行缓存的。在SqlSession中有一个(内存区域)数据结构(HashMap)用于存储缓存数据。不一样的SqlSession之间的缓存数据区域(HashMap)是互相不影响的;MyBatis 的一级缓存是默认开启的,不须要任何的配置。
MyBatis 在开启一个数据库会话时,会建立一个新的 SqlSession 对象,SqlSession 对象中会有一个新的 Executor (Executor是什么?)对象。Executor 对象中持有一个新的PerpetualCache(PerpetualCache是什么?) 对象;当会话结束时,SqlSession 对象及其内部的 Executor 对象还有 PerpetualCache 对象也一并释放掉。
若是 SqlSession 调用了 close()方法,会释放掉一级缓存 PerpetualCache 对象,一级缓存 将不可用。
若是 SqlSession 调用了 clearCache(),会清空 PerpetualCache 对象中的数据,可是该对象 仍可以使用。
若是中间(半路中)sqlSession去执行commit操做(update()、delete()、insert()) ,都会清空SqlSession中的数据,这样作的目的是更新缓存中的数据(PerpetualCache 对象),避免脏读
Mybatis 认为,对于两次查询,若是如下条件都彻底同样,那么就认为它们是彻底相同的两次查询。
传入的 statementId(statementId是什么?)。
查询时要求的结果集中的结果范围。
此次查询所产生的最终要传递给 PreparedStatement 的 Sql 语句字符串。
传递的参数值
MyBatis 的二级缓存是 Application 级别的缓存,它能够提升对数据库查询的效率,以提升应用的性能。二级缓存是 SqlSessionFactory 上的缓存,能够是由一个 SqlSessionFactory 建立的不一样的 SqlSession 之间共享缓存数据。默认并不开启。SqlSession 在执行 commit()或者 close()的时候将数据放入到二级缓存。
二级缓存的开启须要进行配置,实现二级缓存的时候,MyBatis 要求缓存的 POJO 必须是可序列化的, 也就是要求实现 Serializable 接口,为了将缓存数据取出执行反序列化操做,由于二级缓存数据存储介质多种多样,不必定只存在内存中,有可能存在硬盘中。在映射配置文件中配置就能够开启缓存了。
属性,设置为 false。 5. 缓存会使用默认的 Least Recently Used(LRU,最近最少使用的)算法来收回。 6. 根据时间表,好比 No Flush Interval,(CNFI 没有刷新间隔),缓存不会以任什么时候间顺序 来刷新。
在 Mybatis 中若是使用注解式开发,那么注解须要添加在 Mapper 接口中的抽象方法上,在注解中给定须要执行的 SQL 语句便可,这样就能够不须要映射配置文件。MyBatis 支持纯注解方式,支持纯映射配置文件方式,也支持注解和映射配置文件混合形式。当只有接口没有映射配置文件时在 mybatis-cfg.xml 中对于引入映射能够经过加载指定接口类。也可使用指定加载的包。
实例
@Select("select * from users")
List<Users> selectUsersAll();
复制代码
@Select("select * from users where username = #{param1} and usersex= #{param2}")
List<Users> selectUsersByNameAndSexOrder(String username,String usersex);
@Select("select * from users where username = #{name} and usersex = #{sex}")
List<Users> selectUsersByNameAndSexOrder2(@Param("name") String username,@Param("sex") String usersex);
复制代码
#{}里面的参数名称要与实体类的属性名称一致
@Select("select * from users where username = #{username} and usersex = #{usersex}")
List<Users> selectUsersByNameAndSexPOJO(Users users);
复制代码
当key不存在时,则返回null
@Select("select * from users where username = #{keyname} and usersex = #{keysex}")
List<Users> selectUsersByNameAndSexMap(Map<String,String> map);
复制代码
Open Session In View 模式:
Open Session In View 是将一个数据库会话对象绑定到当前请求线程中,在请求期间一直保持数据库会话对象处于 Open 状态,使数据库会话对象在请求的整个期间均可以使用。直到产生响应后关闭当前的数据库会话对象