2023年3月

《\mybatis\day02\14查询缓存-二级缓存-整合ehcache.av》

mybatis的缓存机制(一级缓存二级缓存和刷新缓存)和mybatis整合ehcache-- 这里有做本课程笔记
http://www.360doc.com/content/15/1205/07/29475794_518018352.shtml

EhCache
是一个纯
Java
的进程内缓存框架,是一种广泛使用的开源
Java
分布式缓存,具有快速、精干等特点,是
Hibernate
中默认的
CacheProvider

1.1.1.1
mybatis
整合
ehcache
原理

mybatis
提供二级缓存
Cache
接口,如下:

它的默认实现类:

通过实现
Cache
接口可以实现
mybatis
缓存数据通过其它缓存数据库整合,
mybatis
的特长是
sql
操作,缓存数据的管理不是
mybatis
的特长,为了提高缓存的性能将
mybatis
和第三方的缓存数据库整合,比如
ehcache

memcache

redis
等。

MyBatis的缓存 - 字无忌 - 博客园---看来是个高手,写的博客很不错
http://www.cnblogs.com/jtlgb/p/6037945.html

《\mybatis\day02\16mybatis和spring整合-sqlSessionFactory配置.avi;》

MyBatis学习七:spring和MyBatis整合、逆向工程 - mwj_88的专栏 - CSDN博客--和老是讲课相同--已经拷贝在下方
http://blog.csdn.net/mwj_88/article/details/50315701

添加 source folder 这是一个虚拟目录
点击folder 就是真实目录

spring和 springMVC 和mybatis整合;
1、添加对应的jar包,
2、配置文件 在applicationContext.xml配置sqlSessionFactory和数据源
spring/applicationContext.xml
mybatis/SqlMapConfig.xml
3、有原始DAO开发 和 mapper代理开发


=======【转】MyBatis学习七:spring和MyBatis整合、逆向工程 - mwj_88的专栏 ==============

一、整合思路

需要
spring
通过单例方式管理SqlSessionFactory。

spring和mybatis整合生成代理对象,使用SqlSessionFactory创建SqlSession(spring和mybatis整合自动完成)。

持久层的mapper都需要由spring进行管理。


二、整合之后结构图


三、配置SqlSessionFactory和数据源

在applicationContext.xml配置SqlSessionFactory和数据源。

<!—加载配置文件 --
>

<context:property-placeholderlocation=”classpath:db.properties”/><!—数据源,使用dbcp -->  
<beanid=”dataSource”class=”org.apache.commons.dbcp.BasicDataSource”destroy-method=”close”><property name=”driverClassName”value=”${jdbc.driver}”//继续配置url、username、password、maxActive、maxIdle等  
</bean
> <!--sqlSessionFactory--> <beanid=”sqlSessionFactory”class=”org.mybatis.spring.SqlSessionFactoryBean”><!—加载mybatis的配置文件 --> <propertyname=”configLocation”value=”mybatis/SqlMapConfig.xml”/><!—数据源 --> <propertyname=”datasource”ref=”datasource”/> </bean>

假设已经写好pojo、映射文件(原始dao方式名称为User.xml;代理开发方式为xxMapper.xml)。、在SQLConfigMap.xml中加载映射文件,然后接着开发:


四、原始dao方式


1、dao实现类继承SqlSessionDaoSupport

dao接口实现类需要注入SqlSessionFactory,通过spring进行注入。两种方式:自动注入或者声明配置方式;这里使用声明配置方式,配置dao的bean:让UserDaoImpl实现类继承SqlSessionDaoSupport。

  1. public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao{
  2. @override
  3. public User findUserById(int id) throws Exception{
  4. //继承SqlSessionDaoSupport,通过this.getSqlSession()得到sqlSession
  5. SqlSession
    sqlSession =
    this.getSqlSession();
  6. User
    user =
    sqlSession.selectOne(“test.findUserById”, id);
  7. return user;
  8. <
    span
    style=
    "white-space:pre"
    >
    </
    span
    >}
  9. }

2、配置dao

在applicationContext.xml中配置dao。

  1. <!—原始dao接口 --
    >
  2. <
    bean
    id=”userDao”
    class=”cn.itcast.ssm.dao.UserDaoImpl”
    >
  3. <
    property
    name=”sqlSessionFactory”
    ref=”sqlSessionFactory”
    />
  4. </
    bean
    >

3、测试
  1. public class UserDaoImplTest{
  2. private ApplicationContext applicationContext;
  3. //在setUp这个方法得到spring容器
  4. @Before
  5. public void setUp() throws Exception{
  6. applicationContext =
    new ClassPathXmlApplicationContext(“classpath:spring/applicationContext”)
  7. <
    span
    style=
    "white-space:pre"
    >
    </
    span
    >}
  8. @Test
  9. public void testFindUserById() throws Exception{
  10. UserDao
    userDao = (UserDao)applicationContext.getBean(“userDao”);
  11. User
    user =
    userDao.findUserById(1);
  12. System.out.println(user);
  13. <
    span
    style=
    "white-space:pre"
    >
    </
    span
    >}
  14. }


五、mapper代理开发方式


1、mapper.xml和mapper.java


2、通过MapperFactoryBean创建代理对象
<!—mapper配置MapperFactoryBean:根据mapper接口生成代理对象 -->  
<beanid=”userMapper”class=”org.mybatis.spring.mapper.MapperFactoryBean”><!--mapperInterface指定mapper接口 -->  
<propertyname=”mapperInterface”value=”cn.itcast.ssm.mapper.UserMapper”/><property name=”sqlSessionFactory”ref=”sqlSessionFactory”/></bean>  

此方法问题:需要针对每个mapper进行配置,麻烦。


3、通过MapperScannerConfigurer进行mapper扫描
<!—加载映射文件 -->  //SqlMapConfig.xml中的
<mappers>  
<mapperresource=”sqlmap/User.xml”/><!—批量加载mapper  
指定mapper接口的包名,mybatis自动扫描包下所有mapper接口进行加载。遵循一些规范:需要将mapper接口类名和mapper.xml映射文件名保持一致,
且在一个目录下。上边规范的前提是:使用 的是mapper代理方法。
和spring整合后,使用mapper扫描器,mybatis的配置文件中就不需要配置了
<!-- <package name
=”cn.itcast.ssm.mapper”/>-->//用了下方的Mapper扫描器后,此处的包扫描可以去掉了
-->
</mappers>

<!—mapper批量扫描,从mapper包中扫描出mapper接口,自动创建代理对象并且在spring容器中注册。遵循规范:将mapper.java和mapper.xml映射文件名称保持一致,
且在一个目录中。自动扫描出来的mapper的bean的id为mapper类名(首字母小写) --
> <beanclass=”org.mybatis.spring.mapper.MapperScannerConfigurer”><!—指定扫描的包名。如果扫描多个包,每个包中间使用半角逗号分隔 --> <propertyname=”basePackage”value=”cn.itcast.ssm.mapper”/><property name=”sqlSessionFactoryBeanName”value=”sqlSessionFactory”/></bean> // 这里name必须用sqlSessionFactoryBeanName而不可以用sqlSessionFactory
//不可以<property name=”sqlSessionFactory” ref=”sqlSessionFactory”/>
// 用像2方法中哪样,否则不优先执行<context:property-placeholder location="classpath:db.properties" />


4、测试代码
    1. @Test
    2. public void testFindUserById() throws Exceptino{
    3. UserMapper
      userMapper = (userMapper)applicationContext.getBean(“userMapper”);
    4. User
      user =
      userMapper.findUserById(1);
    5. System.out.println(user);
    6. }

mybatis入门基础(八)-----查询缓存 - 阿赫瓦里 - 博客园
http://www.cnblogs.com/selene/p/4638648.html

1.1
mybatis
缓存介绍

如下图,是
mybatis
一级缓存和二级缓存的区别图解:

Mybatis
一级缓存的作用域是同一个
SqlSession
,在同一个
sqlSession
中两次执行相同的
sql
语句,
第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。
当一个
sqlSession
结束后该
sqlSession
中的一级缓存也就不存在了。
Mybatis
默认开启一级缓存。

================================================

二级缓存:

Mybatis的二级缓存的作用域是一个mapper的namespace,同一个namespace中查询sql可以从缓存中命中。

二级缓存是可以跨session的。

开启二级缓存:

在mapper.xml文件中加入 <cache /> 。

三、二级缓存

3.1二级缓存的工作原理

3.1.1. 首先开启mybatis的二级缓存。

3.1.2. sqlSession1去查询用户id为1的用户信息,查询到用户信息会将查询数据存储到二级缓存中。

3.1.3. 如果SqlSession3去执行相同 mapper下sql,执行commit提交,清空该 mapper下的二级缓存区域的数据。

3.1.4. sqlSession2去查询用户id为1的用户信息,去缓存中找是否存在数据,如果存在直接从缓存中取出数据。

二级缓存与一级缓存区别,二级缓存的范围更大,多个sqlSession可以共享一个UserMapper的二级缓存区域。

UserMapper有一个二级缓存区域(按namespace分) ,其它mapper也有自己的二级缓存区域(按namespace分)。

每一个namespace的mapper都有一个二缓存区域,两个mapper的namespace如果相同,这两个mapper执行sql查询到数据将存在相同的二级缓存区域中。

3.2. 开启二级缓存
(开启两个地方:一个***config.xml 一个是****Mapper.xml)

mybaits的二级缓存是mapper范围级别,除了在SqlMapConfig.xml设置二级缓存的总开关,还要在具体的mapper.xml中开启二级缓存。

在核心配置文件SqlMapConfig.xml中加入

<setting name="cacheEnabled" value="true"/>

描述

允许值

默认值

cacheEnabled

对在此配置文件下的所有cache 进行全局性开/关设置。

true false

true


UserMapper.xml
中开启二缓存,
UserMapper.xml
下的
sql
执行完成会存储到它的缓存区域(
HashMap
)。

a.在mybatis的核心配置文件sqlMapConfig.xml中开启二级缓存,其实默认值就为true,写上方便代码维护。

<!-- 全局参数的配置 -->
    <settings>
        <!-- 开启二级缓存 -->
            <setting name="cacheEnabled" value="true"/>
    </settings> 

b.实体类User实现序列化接口

public class User implements Serializable{
  //属性......
  //getter and setter......  
}

为了将缓存数据取出执行反序列化操作,因为二级缓存数据存储介质多种多样,不一样在内存。

c.Junit测试:

复制代码
// 二级缓存测试
    @Test
    public void testCache2() throws Exception {
        SqlSession sqlSession1 = sqlSessionFactory.openSession();
        SqlSession sqlSession2 = sqlSessionFactory.openSession();
        SqlSession sqlSession3 = sqlSessionFactory.openSession();
        // 创建代理对象
        UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
        // 第一次发起请求,查询id为1的用户
        User user1 = userMapper1.findUserById(1);
        System.out.println(user1);
        
        //这里执行关闭操作,将sqlsession中的数据写到二级缓存区域
        sqlSession1.close();
        
        
        //使用sqlSession3执行commit()操作
        UserMapper userMapper3 = sqlSession3.getMapper(UserMapper.class);
        User user  = userMapper3.findUserById(1);
        user.setUsername("张明明");        userMapper3.updateUser(user);
        //执行提交,清空UserMapper下边的二级缓存
        sqlSession3.commit();
        sqlSession3.close();

        UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
        // 第二次发起请求,查询id为1的用户
        User user2 = userMapper2.findUserById(1);
        System.out.println(user2);

        sqlSession2.close();

    }
复制代码

3.3.禁用二级缓存

在statement中设置useCache=false可以禁用当前select语句的二级缓存,即每次查询都会发出sql去查询,默认情况是true,即该sql使用二级缓存。

<select id="findOrderListResultMap" resultMap="ordersUserMap" useCache="false">

3.4.刷新缓存

在mapper的同一个namespace中,如果有其它insert、update、delete操作数据后需要刷新缓存,如果不执行刷新缓存会出现脏读。

设置statement配置中的flushCache="true" 属性,默认情况下为true即刷新缓存,如果改成false则不会刷新。使用缓存时如果手动修改数据库表中的查询数据会出现脏读。

如下:

<insert id="insertUser" parameterType="com.mybaits.entity.User" flushCache="true">

3.5.Mybatis Cache参数

lushInterval(刷新间隔)可以被设置为任意的正整数,而且它们代表一个合理的毫秒形式的时间段。默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新。

size(引用数目)可以被设置为任意正整数,要记住你缓存的对象数目和你运行环境的可用内存资源数目。默认值是1024。

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

如下例子:

<cache  eviction="FIFO"  flushInterval="60000"  size="512"  readOnly="true"/>

这个更高级的配置创建了一个 FIFO 缓存,并每隔 60 秒刷新,存数结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此在不同线程中的调用者之间修改它们会导致冲突。可用的收回策略有, 默认的是 LRU:

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

3.6.二级缓存应用场景

对于访问多的查询请求且用户对查询结果实时性要求不高,此时可采用mybatis二级缓存技术降低数据库访问量,提高访问速度,业务场景比如:耗时较高的统计分析sql、电话账单查询sql等。

实现方法如下:通过设置刷新间隔时间,由mybatis每隔一段时间自动清空缓存,根据数据变化频率设置缓存刷新间隔flushInterval,比如设置为30分钟、60分钟、24小时等,根据需求而定。

3.7.二级缓存的局限性

mybatis二级缓存对细粒度的数据级别的缓存实现不好,比如如下需求:对商品信息进行缓存,由于商品信息查询访问量大,但是要求用户每次都能查询最新的商品信息,此时如果使用mybatis的二级缓存就无法实现当一个商品变化时只刷新该商品的缓存信息而不刷新其它商品的信息,因为mybaits的二级缓存区域以mapper为单位划分,当一个商品信息变化会将所有商品信息的缓存数据全部清空。解决此类问题需要在业务层根据需求对数据有针对性缓存。

连接方式:

java连接数据库的四种方式 - Cece_2012的专栏 - CSDN博客
http://blog.csdn.net/cece_2012/article/details/7485482

JAVA连接数据库大全 - 语不惊人死不休 - CSDN博客
http://blog.csdn.net/qiaqia609/article/details/8120590

====================

连接池:

尽管Spring并没有提供数据源连接池实现,但是我们有多项可用的方案,包括如下开源的实现:

Apache
Commons DBCP (http://jakarta.apache.org/commons/dbcp);
c3p0
(http://sourceforge.net/projects/c3p0/) ;
BoneCP
(http://jolbox.com/) 。
这些连接池中的大多数都能配置为Spring的数据源,

---------------Java 使用JDBC、DBCP、C3P0访问数据库 - akon_vm的专栏 - CSDN博客--很详尽,看得晕
http://blog.csdn.net/akon_vm/article/details/11600941

---------------c3p0、dbcp、tomcat jdbc pool 连接池区别(推荐使用jdbc pool) - hins - CSDN博客
http://blog.csdn.net/kenhins/article/details/51189436

---------------
dbcp和jdbc连接池什么区别

jdbc 是数据库的访问框架,目前 Java 的程序,访问数据库基本上都会用到。即使 OR mapping 底层也是需要的
DBCP 是用来管理数据库连接池的。不是必须的,有了可以增加并发吞吐量
当然,你也可以自己做一个……,说穿了就是 ObjectPool

---------------使用jdbc-pool
替代
dbcp、c3p0等连接池的原因 - u011267070的博客 - CSDN博客
http://blog.csdn.net/u011267070/article/details/52185938?locationNum=4

---------------数据库连接池c3p0和dbcp - 平淡才是正 - 博客园
http://www.cnblogs.com/haogeBlogs/p/5856302.html

现在常用的开源数据连接池主要有c3p0、dbcp和proxool三种,其中:
hibernate开发组推荐使用c3p0;
spring开发组推荐使用dbcp(dbcp连接池有weblogic连接池同样的问题,就是强行关闭连接或数据库重启后,无法reconnect,告诉连接被重置,这个设置可以解决);
hibernate in action推荐使用c3p0和proxool;

dbcp所需jar:commons-dbcp.jar、commons-pool.jar
c3p0所需jar:c3p0-0.9.2.1.jar mchange-commons-java-0.2.3.4.jar

proxool暂时没有接触到

C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate,Spring等。
dbcp简介:
DBCP(DataBase connection pool),数据库连接池。是 apache 上的一个 java 连接池项目,也是 tomcat 使用的连接池组件。单独使用dbcp需要3个包:common-dbcp.jar,common-pool.jar,common-collections.jar由于建立数据库连接是一个非常耗时耗资源的行为,所以通过连接池预先同数据库建立一些连接,放在内存中,应用程序需要建立数据库连接时直接到连接池中申请一个就行,用完后再放回去。
c3p0与dbcp区别:
dbcp没有自动的去回收空闲连接的功能  c3p0有自动回收空闲连接功能
两者主要是对数据连接的处理方式不同!C3P0提供最大空闲时间,DBCP提供最大连接数。
前者当连接超过最大空闲连接时间时,当前连接就会被断掉。DBCP当连接数超过最大连接数时,所有连接都会被断开。

配置方式:

<!--配置dbcp数据源-->
      <beanid="dataSource2"destroy-method="close"class="org.apache.commons.dbcp.BasicDataSource">
        <propertyname="driverClassName"value="${jdbc.driverClassName}"/>
        <propertyname="url"value="${jdbc.url}"/>
        <propertyname="username"value="${jdbc.username}"/>
        <propertyname="password"value="${jdbc.password}"/>
        <!--池启动时创建的连接数量-->
        <propertyname="initialSize"value="5"/>
        <!--同一时间可以从池分配的最多连接数量。设置为0时表示无限制。-->
        <propertyname="maxActive"value="30"/>
        <!--池里不会被释放的最多空闲连接数量。设置为0时表示无限制。-->
        <propertyname="maxIdle"value="20"/>
        <!--在不新建连接的条件下,池中保持空闲的最少连接数。-->
        <propertyname="minIdle"value="3"/>
        <!--设置自动回收超时连接-->  
        <propertyname="removeAbandoned"value="true" />
        <!--自动回收超时时间(以秒数为单位)-->  
        <propertyname="removeAbandonedTimeout"value="200"/>
        <!--设置在自动回收超时连接的时候打印连接的超时错误--> 
        <propertyname="logAbandoned"value="true"/>
        <!--等待超时以毫秒为单位,在抛出异常之前,池等待连接被回收的最长时间(当没有可用连接时)。设置为-1表示无限等待。-->  
        <propertyname="maxWait"value="100"/>  
      </bean>
      
    <!--配置c3p0数据源-->
    <beanid="dataSource"class="com.mchange.v2.c3p0.ComboPooledDataSource"destroy-method="close">
        <propertyname="jdbcUrl"value="${jdbc.url}" />
        <propertyname="driverClass"value="${jdbc.driverClassName}" />
        <propertyname="user"value="${jdbc.username}" />
        <propertyname="password"value="${jdbc.password}" />
        <!--连接池中保留的最大连接数。Default: 15-->
        <propertyname="maxPoolSize"value="100" />
        <!--连接池中保留的最小连接数。-->
        <propertyname="minPoolSize"value="1" />
        <!--初始化时获取的连接数,取值应在minPoolSize与maxPoolSize之间。Default: 3-->
        <propertyname="initialPoolSize"value="10" />
        <!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0-->
        <propertyname="maxIdleTime"value="30" />
        <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3-->
        <propertyname="acquireIncrement"value="5" />
        <!--JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements
属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。
如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0
--> <propertyname="maxStatements"value="0" /> <!--每60秒检查所有连接池中的空闲连接。Default: 0--> <propertyname="idleConnectionTestPeriod"value="60" /> <!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30--> <propertyname="acquireRetryAttempts"value="30" /> <!--获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效
保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试
获取连接失败后该数据源将申明已断开并永久关闭。Default: false
--> <propertyname="breakAfterAcquireFailure"value="true" /> <!--因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的
时候都将校验其有效性。建议使用idleConnectionTestPeriod或automaticTestTable
等方法来提升连接测试的性能。Default: false
--> <propertyname="testConnectionOnCheckout"value="false" /> </bean>

转:常见Java数据结构&优缺点 - /画家/ - 博客园
http://www.cnblogs.com/earl-yongchang/p/5639161.html

图片也是引用过来的,没有重新上传

数组

优点:查询快,如果知道索引可以快速地存取
缺点:删除慢,大小固定
有序数组
优点:比无序数组查找快
缺点:删除和插入慢,大小固定
优点:提供后进先出的存取方式
缺点:存取其他项很慢
队列

优点:提供先进先出的存取方式
缺点:存取其他项都很慢
链表

优点:插入快,删除快
缺点:查找慢(一个个节点查)
二叉树
优点:查找,插入,删除都快(平衡二叉树)
缺点:删除算法复杂
红-黑树
优点:查找,插入,删除都快,树总是平衡的(局部调整)
缺点:算法复杂

2-3-4树
优点:查找,插入,删除都快,树总是平衡的。类似的树对磁盘存储有用
缺点:算法复杂
哈希表
优点:如果关键字已知则存取速度极快,插入快
缺点:删除慢,如果不知道关键字则存取很慢,对存储空间使用不充分
优点:插入,删除快,对最大数据的项存取很快
缺点:对其他数据项存取很慢
优点:对现实世界建模
缺点:有些算法慢且复杂