在实际开发中,都会使用链接池,由于它能够减小获取链接缩消耗的时间。所谓链接池,就是存储数据库链接的容器。链接池中存储必定数量的数据库链接,当线程须要使用到链接时,就从链接池中获取数据库链接,线程使用完数据库链接会还回链接池中。java
链接池:其实就是一个集合对象,该集合必须是线程安全的;并且线程必须实现对列,知足 ” 先进先出 “ 的特性。web
三种配置方式sql
配置位置:MyBatis主配置文件中,<dataSource>
元素;type属性的值表示采用何种链接池;数据库
POOLED:采用传统的 javax.sql.DataSource
接口规范中的链接池,MyBatis中有该规范的实现;缓存
UNPOOLED:采用传统获取数据库链接的方式,虽然实现了 javax.sql.DataSource
接口,但没有链接池的思想——即须要时才建立数据库链接;安全
JNDI:采用服务器提供的 JNDI 技术实现,来获取 DataSource 对象,不一样服务器的拿到的 DataSource 对象是不一样的;服务器
注意:不是 web 或 maven 工程,是不能使用的。Tomcat 服务器中,采用链接池是 dbcp 链接池。session
什么是事务?mybatis
事物的四大特性ACIDapp
不考虑隔离性会产生的3个问题
解决方法:四种隔离级别
MyBatis 中的事务控制默认没有开启自动提交,可使用 SqlSessionFactory.opensession(boolean autoCommit)
方法建立设置是否开启自动提交事务的 Sqlsession
对象。但有一点须要注意的是:开启了自动提交事务,MyBatis是对一个数据库操做(并不是多个)进行事务提交。没有开启自动提交事务时,是使用 SqlSession
对象的 commit 方法 和 rollback 方法进行事务的提交的回滚。
单参数——定义传入参数的类型,能够是基本类型、引用类型、映射;
多参数——须要在接口类中的抽象方法的参数前使用注解 @Param("")
指定参数名;
<!--接口方法:User findUser(String username, String password); --> <select id="findUser" resultType="*.user"> select * from user where username=#{0} and password=#{1} </select>
<!--User findUser(@Param("username") String username, @Param("password") String password);--> <select id="findUser" resultType="user"> select * from user where username=#{username} and password=#{password} </select>
if 标签:用于进行条件判断, test 属性用于指定判断条件。为了拼接条件, 在 SQL 语句后强行添加 1=1 的恒成立条件
<select id="sel" resultType="user"> select * from user where 1=1 <if test="username != null and username != ''"> and username=#{username} </if> <if test="password != null and password != ''"> and password=#{password} </if> </select>
choose(when otherwise)标签:这是一套标签, 功能相似于 switch...case...
<select id="sel" resultType="user"> select * from user <where> <choose> <when test="username != null and username != ''"> and username = #{username} </when> <when test="password != null and password != ''"> and password = #{password} </when> <otherwise> and 1=1 </otherwise> </choose> </where> </select>
用于管理 where 子句,有以下功能:
<select id="sel" resultType="user"> select * from user <where> <if test="username != null and username != ''"> and username=#{username} </if> <if test="password != null and password != ''"> and password=#{password} </if> </where> </select>
用于维护 update 语句中的 set 子句,功能以下:
<update id="updUser" parameterType="user"> update user <set> id=#{id}, <!-- 防止全部条件不成立时的语法错误 --> <if test="username != null and username != ''"> username=#{username}, </if> <if test="password != null and password != ''"> password=#{password}, </if> </set> where id=#{id} </update>
trim() 标签:用于在先后添加或删除一些内容
<update id="updUser" parameterType="user"> update user <!-- prefix: 前缀, 表示向前面添加内容 prefixOverrides: 从前面删除内容 suffix: 后缀, 表示向后面添加内容 suffixOverrides: 从后面删除内容 --> <trim prefix="set" prefixOverrides="user" suffix="hahah" suffixOverrides=","> username=#{username}, </trim> where id=#{id} </update>
bind标签:用于对数据进行再加工。好比,模糊查询中对数据的拼接
<select id="sel" resultType="user"> select * from user <where> <if test="username!=null and username!=''"> <bind name="username" value="'%' + username + '%'"/> and username like #{username} </if> </where> </select>
foreach标签:用于在 SQL 语句中遍历集合参数, 在 in 查询中使用
<select id="selIn" parameterType="list" resultType="user"> select * from user <where> <foreach collection="list" open="id in (" separator="," close=")" item="item"> #{item} </foreach> </where> </select>
sql/include标签: <sql>
用于提取 SQL 语句, <include>
用于引用 SQL 语句
<sql id="mySql"> select * from user </sql> <select id="selIn" parameterType="list" resultType="user"> <include refid="mySql"/> from t_user where id in <foreach collection="list" open="(" separator="," close=")" item="item"> #{item} </foreach> </select>
问题:在一对多中,当咱们有一个用户,它有100个帐户。1)当查询用户时,要不要把关联的帐户查出来?2)当查询帐户时,要不要把关联的用户查出来?
一对多的关系中,Java 中是使用集合来存储多的一方,若是,仅仅只想查询用户信息,并不关心其帐户的信息,这时,若是还将该用户下的全部帐户查询出来,不只影响效率,也占用内存。
什么是延时加载(懒加载)?——在真正使用数据时才发起查询,不使用时不查询,也就是:按需查询。
什么是当即加载?——无论用不用,只要一调用方法,就发起查询。
什么时候使用延时加载,什么时候使用当即加载?——一对多、多对多:一般采用延时加载;多对一,一对一:一般采用当即加载;
在 mapping 配置文件中,配置 resultMap
元素,在须要使用延迟加载的对象使用 <association>
元素或 collection
元素关联;并经过如下属性,引用查询语句和传递查询条件,MyBatis会将查询结果封装到延迟加载的对象:
但这尚未启用懒加载方式。须要启用懒加载方式,在主配置文件 <settings>
元素中配置如下 setting 子元素:
<settings> <setting name="lazyLoadingEnabled" value="true"/> <setting name="aggressiveLazyLoading" value="false"/> </settings>
在没有启用延迟加载时,MyBatis会加载全部查询数据;启用延迟加载时,当延迟加载的对象被调用,才会加载;
什么是缓冲?——存储在内存中的临时数据;
为何使用缓冲?——减小和数据库的交互次数,提升执行效率;
什么数据能使用缓存,什么数据不能?
一级缓存和二级缓存
指的是 MyBatis 中 SqlSession 对象的缓存。
当执行查询以后,查询结果会同时存入到 SqlSession 提供的一个 Map 区域中;当再次查询相同的数据时,MyBatis 会先去 Map 区域中查找,没有找到在执行查询操做。当 SqlSession 对象消失或清空缓存操做时,一级缓存也就消失了。
如何保证数据库数据和一级缓存数据保持一致(数据同步)?
若是 sqlSession 执行 commit 操做(执行插入、更新、删除),会清空 SqlSession 中的一级缓存,这样作的目的为了让缓存中存储的是最新的信息,避免脏读。
指的是 MyBatis 中 SqlSessionFactory 对象的缓存,有同一个 SqlSessionFactory 对象建立并共享缓存。
二级缓存的使用步骤
让 MyBatis 支持二级缓存(在主配置文件中配置);
<settings> <setting name="cacheEnabled" value="true"/> </settings>
让当前映射文件支持二级缓存(在 mapper 配置文件配置);
<cache/>
让当前操做支持二级缓存(select 元素中配置)
<select id="findAll"resultMap="user" useCache="true"> select * from class </select>
二级缓存中存放的内容是数据,而不是对象。
当使用注解开发时,相同包名下不能有 mapper 配置文件,会发生配置文件解析冲突错误。
@Select()
@Delete()
@Update()
@Insert()
定义属性名与列名映射
@Results(id="UserMap",value={ @Result(id=true,column="",property=""), @Result(column="",property=""), @Result(column="",property=""), })
引用映射,引用 @Results
中的 ID 值
@ResultMap(value={"UserMap"})
一对一
@Results(id="UserMap",value={ @Result(id=true,column="",property=""), @Result(column="",property=""), @Result(column="",property=""), @Result(column="做为查询的列名",property="属性名", one=@One( select="全限定查询方法" fetchType=FetchType.EAGER )) })
使用 @One
注解定义查询方法,根据 column 中的属性做为查询条件,返回一条数据;
LAZY(延迟加载)、EAGER(当即加载)、DEFAULT
;一对多
@Results(id="UserMap",value={ @Result(id=true,column="",property=""), @Result(column="",property=""), @Result(column="",property=""), @Result(column="做为查询的列名",property="属性名", many=@Many( select="全限定查询方法" fetchType=FetchType.LAZY )) })
在主配置文件中配置开启二级缓存;
<settings> <setting name="cacheEnabled" value="true"/> </settings>
在接口类级别上使用 @CacheNamespace(blocking= true)
;