栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Mybatis学习 详细

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Mybatis学习 详细

Mybatis 是一个持久层框架,它可以自定义sql、存储过程、高级映射。使用它,你可以免去书写jdbc、设置参数、获取结果集的操作。通过简单的xml或注解配置和映射原始类型、接口、Java POJO为数据库中的记录 。

Mybatis入门

1.添加mybatis依赖
2.用SqlSessionFactoryBuilder从xml配置文件或java代码中构建SqlSessionFactory。xml配置文件中包含了mybatis系统的核心设置,获取数据库连接实例的数据源(DataSource),决定事务作用域和控制方法的事务管理器(TransactionManager)。
3.SqlSessionFactory生产SqlSession
4.mapper.xml命名空间绑定Mapper接口
5.SqlSession获取Mapper代理类实例,调用方法

Mybatis工作原理? Mybatis关键部分

SqlSessionFactoryBuilder
SqlSessionFactory:全局只需要一个
SqlSession:每个请求要一个,线程不安全
Mapper:映射器是绑定语句的接口
mapper.xml

$和#的区别

#{}:可以获取map中的值或者pojo对象属性的值;

: 可 以 获 取 m a p 中 的 值 或 者 p o j o 对 象 属 性 的 值 ; ​ s e l e c t ∗ f r o m t b l e m p l o y e e w h e r e i d = {}:可以获取map中的值或者pojo对象属性的值; ​ select * from tbl_employee where id= :可以获取map中的值或者pojo对象属性的值;​select∗fromtble​mployeewhereid={id} and last_name=#{lastName}
Preparing: select * from tbl_employee where id=2 and last_name=?
区别:
#{}:是以预编译的形式,将参数设置到sql语句中;PreparedStatement;防止sql注入
${}:取出的值直接拼装在sql语句中;会有安全问题;

Mybatis中javaType和jdbcType对应关系
JDBC Type            Java Type
CHAR                String
VARCHAR                String
LonGVARCHAR            String
NUMERIC                java.math.BigDecimal
DECIMAL                java.math.BigDecimal
BIT                boolean
BOOLEAN                boolean
TINYINT                byte
SMALLINT            short
INTEGER                int
BIGINT                long
REAL                float
FLOAT                double
DOUBLE                double
BINARY                byte[]
VARBINARY            byte[]
LonGVARBINARY                byte[]
DATE                java.sql.Date
TIME                java.sql.Time
TIMESTAMP            java.sql.Timestamp
CLOB                Clob
BLOB                Blob
ARRAY                Array
DISTINCT            mapping of underlying type
STRUCT                Struct
REF                            Ref
DATAlink            java.net.URL[color=red][/color]
mybatis缓存 一级缓存

默认开启一级缓存。一级缓存是对同一个sqlSession而言的。

同一个sqlSession,会将sql和实参生成key,结果作为value,放入一个map中,第二次相同的sql和实参时,直接返回map中的结果select标签的属性flushCache可控制是否清空缓存。不同sqlSession的缓存相互隔离update、delete、insert之后清空缓存 二级缓存

默认关闭。二级缓存的作用域是namespace。二级缓存,存的是结果序列化后的,因此实体类要实现Serializable。update、delete、insert后会清空缓存。在读多写少时开启。




xml配置文件的结构
configuration(配置)
	properties(属性)
	settings(设置)
	typeAliases(类型别名)
	typeHandlers(类型处理器)
	objectFactory(对象工厂)
	plugins(插件)
	environments(环境配置)
		environment(环境变量)
			transactionManager(事务管理器)
			dataSource(数据源)
	databaseIdProvider(数据库厂商标识)
	mappers(映射器)
属性(properties)

属性中声明的属性值可以被当前配置文件中的其他标签使用。提高属性的复用性,同时便于我们修改。

属性的来源

子标签property声明的properties标签的resource属性指定的.properties文件properties标签的url属性指定的.properties文件方法传入的参数

优先级:方法传入的参数 > resource/url指定的.properties文件 > 子标签property声明的。高优先级的会覆盖低优先级的同名属性

可以为占位符设置默认值,这个特性默认关闭,需要开启。

  
   

这个特性默认是关闭的。要启用这个特性,需要添加一个特定的属性来开启这个特性。例如:


  
   

默认的分隔符可以自定义

  
   



  
  

设置(Settings) useGeneratedKeys

useGeneratedKeys,新增记录之后返回自增的主键ID。
全局设置useGeneratedKeys,对注解映射器生效,对xml映射器不生效。注解映射器可以通过@Options注解设置useGeneratedKeys。xml映射器需设置insert标签的属性useGeneratedKeys。





此时,在接口映射中添加记录之后将返回主键ID。

public interface TestMapper {
    // 受全局useGeneratedKeys参数控制,添加记录之后将返回主键id
    @Insert("insert into test(name,descr,url,create_time,update_time) values(#{name},#{descr},#{url},now(),now())")
    Integer insertOneTest(Test test);
}

// 在接口映射器中设置的useGeneratedKeys参数值将会覆盖在settings元素中设置全局useGeneratedKeys参数值
@Options(useGeneratedKeys = false, keyProperty = "id", keyColumn = "id")
@Insert("insert into test(name,descr,url,create_time,update_time) values(#{name},#{descr},#{url},now(),now())")
Integer insertOneTest(Test test);
在xml映射器中配置useGeneratedKeys参数


    insert into test(name,descr,url,create_time,update_time) 
    values(#{name},#{descr},#{url},now(),now())

设置名描述默认值
mapUnderscoreToCamelCase是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。False
logImpl指定 MyBatis 所用日志的具体实现,未指定时将自动查找。未设置
jdbcTypeForNull当没有为参数指定特定的 JDBC 类型时,空值的默认 JDBC 类型。 某些数据库驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。OTHER
defaultExecutorType配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(PreparedStatement); BATCH 执行器不仅重用语句还会执行批量更新。SIMPLE
cacheEnabled全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。true
lazyLoadingEnabled延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。false
aggressiveLazyLoading开启时,任一方法的调用都会加载该对象的所有延迟加载属性。 否则,每个延迟加载属性会按需加载(参考 lazyLoadTriggerMethods)。false (在 3.4.1 及之前的版本中默认为 true)
autoMappingBehavior指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示关闭自动映射;PARTIAL 只会自动映射没有定义嵌套结果映射的字段。 FULL 会自动映射任何复杂的结果集(无论是否嵌套)。PARTIAL
mapUnderscoreToCamelCase

1.第一种使用resultMap一一对应映射





	
		
		
		
		
		
	
	
	
		select
			comment_id,
			prescription_order_id,
			customer_id,
			content,
			grade
		from
			tb_comment_info
		
			comment_id=2
		
	


defaultExecutorType

mybatis提供三种sql执行器,分别是SIMPLE、REUSE、BATCH。
SIMPLE是默认执行器,根据对应的sql直接执行,不会做一些额外的操作。
REUSE是可重用执行器,重用对象是Statement(即该执行器会缓存同一个sql的Statement,省去Statement的重新创建,优化性能)(即会重用预处理语句)
BATCH执行器会重用预处理语句,并执行批量更新。
即executor-type有三种值,即SIMPLE、REUSE、BATCH。
执行效果:
executor-type值为SIMPLE、REUSE,可通过insert、update、delete方法的返回值判断sql是否执行成功,返回非0表示执行sql成功的条数,返回0表示sql执行失败
executor-type值为BATCH,insert、update、delete方法返回值一直会是负数-2147482646,在该模式下insert、update、delete返回值将无任何意义,不能作为判断sql执行成功的判断依据
BATCH下事务不能自动提交。

SimpleExecutor 比 ReuseExecutor 的性能要差 , 因为 SimpleExecutor 没有做 PSCache。为什么做了 PSCache 性能就会高呢 , 因为当SQL越复杂占位符越多的时候预编译的时间也就越长,创建一个PreparedStatement对象的时间也就越长。猜想中BatchExecutor比ReuseExecutor功能强大性能高,实际上并非如此,BatchExecutor是没有做PSCache的。BatchExecutor 与 SimpleExecutor 和 ReuseExecutor 还有一个区别就是 , BatchExecutor 的事务是没法自动提交的。因为 BatchExecutor 只有在调用了 SqlSession 的 commit 方法的时候,它才会去执行 executeBatch 方法。
————————————————
版权声明:本文为CSDN博主「诺浅」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq32933432/article/details/104514028

在mybatis+spring中ExecutorType的使用
1、在spring配置文件中添加批量执行的SqlSessionTemplate


    
    

autoMappingBehavior

自动映射
自动映射详解文章
对于咱们开发来说,自动映射确实可以帮助我们节省一些代码,不过也存在一些隐患,我们希望自己开发的系统是健壮的,建议大家写mapper xml的时候,还是花点时间将映射的配置都给写上去,这样能够杜绝一些隐患,使我们的系统更稳定。

aggressiveLazyLoading

现在可以更明确aggressiveLazyLoading的作用了:
true:
只要调用任意具有懒加载特性的对象的任意一个属性将完整加载整个对象,即触发级联效果。
false:
只加载调用的属性,不调用的属性不加载。

jdbcTypeForNull

不要依赖mybatis的jdbcTypeForNull全局设置,应该对每个#{xxx, jdbcType=}都指定jdbcType

typeAliases

类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。例如:


  
  
  
  
  
  

也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,比如:


  

每一个在包 domain.blog 中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。 比如 domain.blog.Author 的别名为 author;若有注解,则别名为其注解值。见下面的例子:

@Alias("author")
public class Author {
    ...
}

下面是一些为常见的 Java 类型内建的类型别名。它们都是不区分大小写的,注意,为了应对原始类型的命名重复,采取了特殊的命名风格。

别名	映射的类型
_byte	byte
_long	long
_short	short
_int	int
_integer	int
_double	double
_float	float
_boolean	boolean
string	String
byte	Byte
long	Long
short	Short
int	Integer
integer	Integer
double	Double
float	Float
boolean	Boolean
date	Date
decimal	BigDecimal
bigdecimal	BigDecimal
object	Object
map	Map
hashmap	HashMap
list	List
arraylist	ArrayList
collection	Collection
iterator	Iterator
类型处理器(typeHandlers)

MyBatis 在设置预处理语句(PreparedStatement)中的参数或从结果集中取出一个值时, 都会用类型处理器将获取到的值以合适的方式转换成 Java 类型。下表描述了一些默认的类型处理器。

提示 从 3.4.5 开始,MyBatis 默认支持 JSR-310(日期和时间 API) 。

类型处理器	Java 类型	JDBC 类型
BooleanTypeHandler	java.lang.Boolean, boolean	数据库兼容的 BOOLEAN
ByteTypeHandler	java.lang.Byte, byte	数据库兼容的 NUMERIC 或 BYTE
ShortTypeHandler	java.lang.Short, short	数据库兼容的 NUMERIC 或 SMALLINT
IntegerTypeHandler	java.lang.Integer, int	数据库兼容的 NUMERIC 或 INTEGER
LongTypeHandler	java.lang.Long, long	数据库兼容的 NUMERIC 或 BIGINT
FloatTypeHandler	java.lang.Float, float	数据库兼容的 NUMERIC 或 FLOAT
DoubleTypeHandler	java.lang.Double, double	数据库兼容的 NUMERIC 或 DOUBLE
BigDecimalTypeHandler	java.math.BigDecimal	数据库兼容的 NUMERIC 或 DECIMAL
StringTypeHandler	java.lang.String	CHAR, VARCHAR
...

你可以重写已有的类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型。 具体做法为:实现 org.apache.ibatis.type.TypeHandler 接口, 或继承一个很便利的类 org.apache.ibatis.type.baseTypeHandler, 并且可以(可选地)将它映射到一个 JDBC 类型。

result标签指定typeHandler

	
		
		
		
		
	
	
   SELECT  NOW() FROM dual 
  
  
  
属性	描述
id	在命名空间中唯一的标识符,可以被用来引用这条语句。
parameterType	将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。
resultType	期望从这条语句中返回结果的类全限定名或别名。 注意,如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身的类型。 resultType 和 resultMap 之间只能同时使用一个。
resultMap	对外部 resultMap 的命名引用。结果映射是 MyBatis 最强大的特性,如果你对其理解透彻,许多复杂的映射问题都能迎刃而解。 resultType 和 resultMap 之间只能同时使用一个。
flushCache	将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:false。
useCache	将其设置为 true 后,将会导致本条语句的结果被二级缓存缓存起来,默认值:对 select 元素为 true。
timeout	这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖数据库驱动)。
fetchSize	这是一个给驱动的建议值,尝试让驱动程序每次批量返回的结果行数等于这个设置值。 默认值为未设置(unset)(依赖驱动)。
statementType	可选 STATEMENT,PREPARED 或 CALLABLE。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。
resultSetType	FORWARD_ONLY,SCROLL_SENSITIVE, SCROLL_INSENSITIVE 或 DEFAULT(等价于 unset) 中的一个,默认值为 unset (依赖数据库驱动)。
databaseId	如果配置了数据库厂商标识(databaseIdProvider),MyBatis 会加载所有不带 databaseId 或匹配当前 databaseId 的语句;如果带和不带的语句都有,则不带的会被忽略。
resultOrdered	这个设置仅针对嵌套结果 select 语句:如果为 true,将会假设包含了嵌套结果集或是分组,当返回一个主结果行时,就不会产生对前面结果集的引用。 这就使得在获取嵌套结果集的时候不至于内存不够用。默认值:false。
resultSets	这个设置仅适用于多结果集的情况。它将列出语句执行后返回的结果集并赋予每个结果集一个名称,多个名称之间以逗号分隔。
insert, update 和 delete





属性	描述
id	在命名空间中唯一的标识符,可以被用来引用这条语句。
parameterType	将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。
flushCache	将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:(对 insert、update 和 delete 语句)true。
timeout	这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖数据库驱动)。
statementType	可选 STATEMENT,PREPARED 或 CALLABLE。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。
useGeneratedKeys	(仅适用于 insert 和 update)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系型数据库管理系统的自动递增字段),默认值:false。
keyProperty	(仅适用于 insert 和 update)指定能够唯一识别对象的属性,MyBatis 会使用 getGeneratedKeys 的返回值或 insert 语句的 selectKey 子元素设置它的值,默认值:未设置(unset)。如果生成列不止一个,可以用逗号分隔多个属性名称。
keyColumn	(仅适用于 insert 和 update)设置生成键值在表中的列名,在某些数据库(像 PostgreSQL)中,当主键列不是表中的第一列的时候,是必须设置的。如果生成列不止一个,可以用逗号分隔多个属性名称。
databaseId	如果配置了数据库厂商标识(databaseIdProvider),MyBatis 会加载所有不带 databaseId 或匹配当前 databaseId 的语句;如果带和不带的语句都有,则不带的会被忽略。

首先,如果你的数据库支持自动生成主键的字段(比如 MySQL 和 SQL Server),那么你可以设置 useGeneratedKeys=”true”,然后再把 keyProperty 设置为目标属性就 OK 了。例如,如果上面的 Author 表已经在 id 列上使用了自动生成,那么语句可以修改为:


  insert into Author (username,password,email,bio)
  values (#{username},#{password},#{email},#{bio})

如果你的数据库还支持多行插入, 你也可以传入一个 Author 数组或集合,并返回自动生成的主键。


  insert into Author (username, password, email, bio) values
  
    (#{item.username}, #{item.password}, #{item.email}, #{item.bio})
  

对于不支持自动生成主键列的数据库和可能不支持自动生成主键的 JDBC 驱动,MyBatis 有另外一种方法来生成主键。


  
    select CAST(RANDOM()*1000000 as INTEGER) a from SYSIBM.SYSDUMMY1
  
  insert into Author
    (id, username, password, email,bio, favourite_section)
  values
    (#{id}, #{username}, #{password}, #{email}, #{bio}, #{favouriteSection,jdbcType=VARCHAR})

foreach

1、foreach的属性
  item:集合中元素迭代时的别名,必填
  index:在list和array中,index是元素的序号;在map中,index是元素的key,可选
  open:foreach代码的开始符号,一般是 ‘(’ 并和 ‘)’ 合用,常用在in(),values()时,可选
  separator:元素之间的分隔符,可选
  close:foreach代码的关闭符号,一般是 ‘)’ 并和 '('合用,常用在in(),values()时,可选
  collection:foreach迭代的对象,作为入参时,List对象默认用 list 代替,数组对象用 array代替。Map对象没有默认的键。

同时可以在作为入参时使用@param(“xxx”)来设置键,这时,默认的list、array将会失效。
官方说明:
注意 你可以将一个 List 实例或者数组作为参数对象传给 MyBatis,当你这么做的时候,MyBatis 会自动将它包装在一个 Map 中并以名称为键。List 实例将会以“list”作为键,而数组实例的键将是“array”。

修改 jdbcUrl 允许执行多条语句

jdbc:mysql://localhost:3306/db3?serverTimezone=Asia/Shanghai&allowMultiQueries=true

sql

这个元素可以用来定义可重用的 SQL 代码片段,以便在其它语句中使用。 参数可以静态地(在加载的时候)确定下来,并且可以在不同的 include 元素中定义不同的参数值。比如:

 ${alias}.id,${alias}.username,${alias}.password 

参数

之前见到的所有语句都使用了简单的参数形式。但实际上,参数是 MyBatis 非常强大的元素。

和 MyBatis 的其它部分一样,几乎总是可以根据参数对象的类型确定 javaType,除非该对象是一个 HashMap。这个时候,你需要显式指定 javaType 来确保正确的类型处理器(TypeHandler)被使用。

提示 JDBC 要求,如果一个列允许使用 null 值,并且会使用值为 null 的参数,就必须要指定 JDBC 类型(jdbcType)。阅读 PreparedStatement.setNull()的 JavaDoc 来获取更多信息。

要更进一步地自定义类型处理方式,可以指定一个特殊的类型处理器类(或别名),比如:
#{age,javaType=int,jdbcType=NUMERIC,typeHandler=MyTypeHandler}

但大多时候,你只须简单指定属性名,顶多要为可能为空的列指定 jdbcType,其他的事情交给 MyBatis 自己去推断就行了。

#{firstName}
#{middleInitial,jdbcType=VARCHAR}
#{lastName}
字符串替换

默认情况下,使用 #{} 参数语法时,MyBatis 会创建 PreparedStatement 参数占位符,并通过占位符安全地设置参数(就像使用 ? 一样)。 这样做更安全,更迅速,通常也是首选做法,不过有时你就是想直接在 SQL 语句中直接插入一个不转义的字符串。 比如 ORDER BY 子句,这时候你可以:
ORDER BY ${columnName}

当 SQL 语句中的元数据(如表名或列名)是动态生成的时候,字符串替换将会非常有用。 举个例子,如果你想 select 一个表任意一列的数据时,

@Select("select * from user where ${column} = #{value}")
User findByColumn(@Param("column") String column, @Param("value") String value);

提示 用这种方式接受用户的输入,并用作语句参数是不安全的,会导致潜在的 SQL 注入攻击。因此,要么不允许用户输入这些字段,要么自行转义并检验这些参数。

结果映射

resultMap 元素是 MyBatis 中最重要最强大的元素。它可以让你从 90% 的 JDBC ResultSets 数据提取代码中解放出来,并在一些情形下允许你进行一些 JDBC 不支持的操作。

resultType, MyBatis 会在幕后自动创建一个 ResultMap,再根据属性名来映射列到 JavaBean 的属性上。如果列名和属性名不能匹配上,可以在 SELECt 语句中设置列别名(这是一个基本的 SQL 特性)来完成匹配,或者开启驼峰转换(驼峰转换resultType不能为map)。比如:


  select user_id, user_name, hashed_password
  from some_table
  where id = #{id}

高级结果映射

  SELECT * FROM BLOG WHERe ID = #{id}



  select
    B.id            as blog_id,
    B.title         as blog_title,
    B.author_id     as blog_author_id,
    A.id            as author_id,
    A.username      as author_username,
    A.password      as author_password,
    A.email         as author_email,
    A.bio           as author_bio
  from Blog B left outer join Author A on B.author_id = A.id
  where B.id = #{id}


  
  
  



  
  
  
  
  


  
  
  
    
    
    
    
    
  




那如果博客(blog)有一个共同作者(co-author)该怎么办?select 语句看起来会是这样的:


  select
  B.id as blog_id,
  B.title as blog_title,
  B.author_id as blog_author_id,
  P.id as post_id,
  P.subject as post_subject,
  P.body as post_body,
  from Blog B
  left outer join Post P on B.id = P.blog_id
  where B.id = #{id}

非常重要: id 元素在嵌套结果映射中扮演着非常重要的角色。你应该总是指定一个或多个可以唯一标识结果的属性。 虽然,即使不指定这个属性,MyBatis 仍然可以工作,但是会产生严重的性能问题。 只需要指定可以唯一标识结果的最少属性。显然,你可以选择主键(复合主键也可以)。


  
  
  
    
    
    
  

集合的多结果集(ResultSet) 鉴别器

有时候,一个数据库查询可能会返回多个不同的结果集(但总体上还是有一定的联系的)。 鉴别器(discriminator)元素就是被设计来应对这种情况的,另外也能处理其它情况,例如类的继承层次结构。 鉴别器的概念很好理解——它很像 Java 语言中的 switch 语句。


  
  
  
  
  
  
  
    
    
    
    
  


  
  
  
  
  
  
  
    
      
    
    
      
      
    
    
      
    
    
      
    
  

自动映射

有三种自动映射等级:

NONE - 禁用自动映射。仅对手动映射的属性进行映射。
PARTIAL - 对除在内部定义了嵌套结果映射(也就是连接的属性)以外的属性进行映射
FULL - 自动映射所有属性。
默认值是 PARTIAL,这是有原因的。当对连接查询的结果使用 FULL 时,连接查询会在同一行中获取多个不同实体的数据,因此可能导致非预期的映射。

缓存

默认情况下,只启用了本地的会话缓存,它仅仅对一个会话中的数据进行缓存。 要启用全局的二级缓存,只需要在你的 SQL 映射文件中添加一行:


基本上就是这样。这个简单语句的效果如下:

映射语句文件中的所有 select 语句的结果将会被缓存。
映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存。
缓存会使用最近最少使用算法(LRU, Least Recently Used)算法来清除不需要的缓存。
缓存不会定时进行刷新(也就是说,没有刷新间隔)。
缓存会保存列表或对象(无论查询方法返回哪种)的 1024 个引用。
缓存会被视为读/写缓存,这意味着获取到的对象并不是共享的,可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。


可用的清除策略有:
LRU – 最近最少使用:移除最长时间不被使用的对象。
FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
SOFT – 软引用:基于垃圾回收器状态和软引用规则移除对象。
WEAK – 弱引用:更积极地基于垃圾收集器状态和弱引用规则移除对象。
默认的清除策略是 LRU。

flushInterval(刷新间隔)属性可以被设置为任意的正整数,设置的值应该是一个以毫秒为单位的合理时间量。 默认情况是不设置,也就是没有刷新间隔,缓存仅仅会在调用语句时刷新。

size(引用数目)属性可以被设置为任意正整数,要注意欲缓存对象的大小和运行环境中可用的内存资源。默认值是 1024。

readOnly(只读)属性可以被设置为 true 或 false。只读的缓存会给所有调用者返回缓存对象的相同实例。 因此这些对象不能被修改。这就提供了可观的性能提升。而可读写的缓存会(通过序列化)返回缓存对象的拷贝。 速度上会慢一些,但是更安全,因此默认值是 false。

使用自定义缓存 动态 SQL

动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。

if

使用动态 SQL 最常见情景是根据条件包含 where 子句的一部分。比如:


  SELECT * FROM BLOG WHERe state = ‘ACTIVE’
  
    
      AND title like #{title}
    
    
      AND author_name like #{author.name}
    
    
      AND featured = 1
    
  

trim、where、set

有问题的select


  SELECT * FROM BLOG
  
    
         state = #{state}
    
    
        AND title like #{title}
    
    
        AND author_name like #{author.name}
    
  

where 元素只会在子元素返回任何内容的情况下才插入 “WHERe” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。
如果 where 元素与你期望的不太一样,你也可以通过自定义 trim 元素来定制 where 元素的功能。比如,和 where 元素等价的自定义 trim 元素为:


  ...

prefixOverrides 属性会忽略通过管道符分隔的文本序列(注意此例中的空格是必要的)。上述例子会移除所有 prefixOverrides 属性中指定的内容,并且插入 prefix 属性中指定的内容。

用于动态更新语句的类似解决方案叫做 set。set 元素可以用于动态包含需要更新的列,忽略其它不更新的列。比如:


  update Author
    
      username=#{username},
      password=#{password},
      email=#{email},
      bio=#{bio}
    
  where id=#{id}

来看看与 set 元素等价的自定义 trim 元素吧:


  ...

foreach

动态 SQL 的另一个常见使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候)。比如:


  
  SELECT * FROM BLOG
  WHERe title LIKE #{pattern}

多数据库支持

如果配置了 databaseIdProvider,你就可以在动态代码中使用名为 “_databaseId” 的变量来为不同的数据库构建特定的语句。比如下面的例子:


  
    
      select seq_users.nextval from dual
    
    
      select nextval for seq_users from sysibm.sysdummy1"
    
  
  insert into users values (#{id}, #{name})

动态 SQL 中的插入脚本语言

MyBatis 从 3.2 版本开始支持插入脚本语言,这允许你插入一种语言驱动,并基于这种语言来编写动态 SQL 查询语句。

Java API SQL 语句构建器
String sql = "SELECT P.ID, P.USERNAME, P.PASSWORD, P.FULL_NAME, "
"P.LAST_NAME,P.CREATED_ON, P.UPDATED_ON " +
"FROM PERSON P, ACCOUNT A " +
"INNER JOIN DEPARTMENT D on D.ID = P.DEPARTMENT_ID " +
"INNER JOIN COMPANY C on D.COMPANY_ID = C.ID " +
"WHERe (P.ID = A.ID AND P.FIRST_NAME like ?) " +
"OR (P.LAST_NAME like ?) " +
"GROUP BY P.ID " +
"HAVINg (P.LAST_NAME like ?) " +
"OR (P.FIRST_NAME like ?) " +
"ORDER BY P.ID, P.FULL_NAME";

MyBatis 3 提供了方便的工具类来帮助解决此问题。借助 SQL 类,我们只需要简单地创建一个实例,并调用它的方法即可生成 SQL 语句。让我们来用 SQL 类重写上面的例子:

private String selectPersonSql() {
  return new SQL() {{
    SELECT("P.ID, P.USERNAME, P.PASSWORD, P.FULL_NAME");
    SELECT("P.LAST_NAME, P.CREATED_ON, P.UPDATED_ON");
    FROM("PERSON P");
    FROM("ACCOUNT A");
    INNER_JOIN("DEPARTMENT D on D.ID = P.DEPARTMENT_ID");
    INNER_JOIN("COMPANY C on D.COMPANY_ID = C.ID");
    WHERe("P.ID = A.ID");
    WHERe("P.FIRST_NAME like ?");
    OR();
    WHERe("P.LAST_NAME like ?");
    GROUP_BY("P.ID");
    HAVINg("P.LAST_NAME like ?");
    OR();
    HAVINg("P.FIRST_NAME like ?");
    ORDER_BY("P.ID");
    ORDER_BY("P.FULL_NAME");
  }}.toString();
}
日志

Mybatis 通过使用内置的日志工厂提供日志功能。内置日志工厂将会把日志工作委托给下面的实现之一:

SLF4J
Apache Commons Logging
Log4j 2
Log4j (deprecated since 3.5.9)
JDK logging
MyBatis 内置日志工厂基于运行时自省机制选择合适的日志工具。它会使用第一个查找得到的工具(按上文列举的顺序查找)。如果一个都未找到,日志功能就会被禁用。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/781369.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号