Mybatis

配置文件:
全局配置文件(配置数据源、事务运行时信息)
映射文件(执行statement的相关信息,包括sql语句、输入参数、输出结果)

SqlSession(会话)
作用:它是一个面向程序员的接口,程序员通过该接口可以对数据库进行增删改查方法,该接口有一个默认实现:DefaultSqlSession。

executor(执行器)
作用:SqlSession本身不能直接操作数据库,需要通过executor接口来真正的操作数据库。该接口有两个实现:基本执行器、缓存执行器(默认)。

MappedStatement
作用:它封装了执行statement时的信息。包括sql语句、输入参数、输出结果。

谨慎使用${}

${value} 有sql注入风险,会直接拼上从java代码里传来的参数。

<select id="findUsersByName" parameterType="java.lang.String"
        resultType="com.itcast.model.User">
        SELECT * FROM USER WHERE username LIKE '%${value}%' 
    </select>

执行结果:

2017-03-23 22:26:04,087 [main] DEBUG [test.findUsersByName] - ==>  Preparing: SELECT * FROM USER WHERE username LIKE '%小%' 
2017-03-23 22:26:04,130 [main] DEBUG [test.findUsersByName] - ==> Parameters: 
2017-03-23 22:26:04,156 [main] DEBUG [test.findUsersByName] - <==      Total: 3

主键返回之自增主键

<!-- 添加用户 -->
<!-- selectKey:查询主键,在标签内需要输入查询主键的sql -->
<!-- order:指定查询主键的sql和insert语句的执行顺序,相当于insert语句来说 -->
<!-- LAST_INSERT_ID:该函数是mysql的函数,获取自增主键的ID,它必须配合insert语句一起使用 -->
<insert id="insertUser" parameterType="com.itcast.model.User">
<selectKey keyProperty="id" resultType="int" order="AFTER">
SELECT LAST_INSERT_ID() 
</selectKey>
    
INSERT INTO USER (username,birthday,sex,address) VALUES(#{username},#{birthday},#{sex},#{address})
</insert>

主键返回之UUID

UUID()函数是mysql的函数。

<insert id="insertUser2" parameterType="com.itcast.model.User">
<selectKey keyProperty="id" resultType="string" order="BEFORE">
SELECT UUID() 
</selectKey>
    
INSERT INTO USER (id,username,birthday,sex,address)
VALUES(#{id},#{username},#{birthday},#{sex},#{address})
</insert>

主键返回之序列

序列也就是sequence,它是Oracle的主键生成策略。

<!-- 自增主键之UUID -->
<insert id="insertUser3" parameterType="com.itcast.model.User">
<selectKey keyProperty="id" resultType="int" order="BEFORE">
SELECT seq.nextval FROM dual
</selectKey>
    
INSERT INTO USER (id,username,birthday,sex,address)
VALUES(#{id},#{username},#{birthday},#{sex},#{address})
</insert>

#{}${}

#{}表示占位符?#{}接收简单类型的参数时,里面的名称可以任意;
${}表示拼接符,${}接收简单类型的参数时,里边的名称必须时value;
${}里面的值会原样输出,不加解析(例如:如果该参数值是字符串,则不会添加引号);
${}存在sql注入的风险,但是有些场景下必须使用,例如排序后面会动态传人排序的列名。

parameterType和resultType

parameterType指定输入参数 的java类型,parameterType只有一个,也就是说传入参数只能有一个。
resultType指定输出结果的java类型,如果返回的是集合,则指单条记录的java类型。

selectOne和selectList

selectOne查询单个对象;selectList查询集合对象。

开发Dao的方式

SqlSessionFactory,它的生命周期,应该在应用范围,全局范围只有一个工厂,使用单例模式来实现这个功能。与spring集成之后,由spring来对其进行单例管理。

SqlSession内部含有一块数据区域,存在线程不安全问题,所以应该将sqlSession声明到方法内部。

原始dao的开发方式

即开发dao接口和dao实现类

Mapper代理的开发方式

即开发mapper接口(就是Dao接口);
Mapper代理使用的是JDK的代理策略。

mapper代理的开发规范

  1. mapper接口的全限定名要和mapper映射文件的namespace值一致;
  2. mapper接口的方法名要和mapper映射文件的statement(sql)的id一致;
  3. mapper接口的方法参数类型和mapper映射文件的statement(sql)的paramterType一致;
  4. mapper接口的返回值类型要和mapper映射文件的statement(sql)的resultType一致。

mapper映射文件

在config下创建mapper目录,然后创建UserMapper.xml(这是mybatis的命名规范,当然,也不是必须使用这个名称)。

具体使用

@Test
public void testFindUserById() throws Exception {
        
// 1. 获取session会话
SqlSession sqlSession = sqlSessionFactory.openSession();
        
// 2. mybatis创建mapper代理对象
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        
// 3. 调用接口
User user = mapper.findUserById(1);
        
System.out.println(user);

// 4. 关闭会话
sqlSession.close();
}

延迟加载

什么是延迟加载

resultMap中的association 和 collection 标签具有延迟加载的功能。

延迟加载的意思是说,在关联查询的时候,利用延迟加载,先加载主信息。按需加载关联信息。这样会大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。

设置延迟加载
Mybatis默认是不开启延迟加载功能的,我们需要手动开启。需要在mybatis全局配置文件中的setting标签中开启延迟加载功能。

<!--开启延迟加载功能 -->
<settings>
    <!-- lazyLoadingEnabled:延迟加载启用,默认是false -->
    <setting name="lazyLoadingEnabled" value="true" />
    <!--aggressiveLazyLoading:积极的懒加载,false表示按需加载,默认是true -->
    <setting name="aggressiveLazyLoading" value="false" />
</settings>

Mybatis 的缓存

一级缓存:sqlSession,在sqlSession中又一个数据区域,是map结构,这个区域就是一级缓存区域。一级缓存中的key是由sql语句、条件、statement等信息组成一个唯一值。一级缓存中的value,就是查询出的结果对象。

二级缓存:同一个namespace下的mapper,二级缓存中,也有一个map结构,这个区域就是一级缓存区域。一级缓存中的key是由sql语句、条件、statement等信息组成一个唯一值。一级缓存中的value,就是查询出的结果对象。

一级缓存是默认开启的,二级缓存默认关闭。

整合ehcache

Mybatis本身是一个持久层框架,它不是专门的缓存框架,所以它对缓存的实现不够好,它本身不支持分布式缓存。

Ehcache 是一个分布式缓存。

整合思路
Cache是一个接口,它的默认实现是mybatis的PerpetualCache。如果想整合mybatis的二级缓存,那么实现Cache接口即可。

  1. 添加jar包
  2. 开启在mybatis总配置文件中,开启二级缓存
<settings>
        <!-- 开启二级缓存总开关 -->
        <setting name="cacheEnabled" value="true" />
    </settings>
  1. 在mapper文件中添加cache标签
<cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>
  1. 在config目录下,添加ehcache的配置文件
  2. 相关的类要实现序列化接口。

mybatis 二级缓存的应用场景

使用场景:对于访问响应速度要求高,但是实时性不高的查询,可以采用二级缓存。
注意:在使用二级缓存的时候,要设置一下刷新间隔(cache标签中有一个flashInterval属性)来定时刷新二级缓存,这个刷新间隔根据具体需求来设置,比如设置30分钟、60分钟等,单位为毫秒。

mybatis二级缓存的局限性

mybatis二级缓存对细粒度的数据,缓存实现不好。

场景:对商品信息进行缓存,由于商品信息查询访问量大,但是要求用户每次查询都是最新的商品信息,此时如果使用二级缓存,就无法实现当一个商品的属性发生变化时只刷新该商品的缓存信息。因为mybatis的二级缓存是mapper级别的,当一个商品的信息发生更新,所有的商品缓存信息都会被清空。
解决此类问题,需要在业务层根据需求对数据有针对性的缓存。
比如可以对经常变化的数据操作单独放到另一个namespace的mapper中。

分布式
一个tomcat大概支持400个左右的并发访问量。
负载均衡,ngnix做负载均衡。

ngnix负载均衡,软负载的策略,硬负载策略。
对缓存进行
为了高可用,高并发。

带宽有限制,100M已经很大了。带宽优化来解决高并发。

  1. 应用服务器做一些负载,根据并发数去线性扩展。
  2. 数据库是影响高并发的关键部分。数据库读写分离可以提高性能,读写数据库之间有一个同步机制。
  3. 互联网应用必须做三个测试:功能测试、性能测试、安全测试。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容