证明IBATIS缓存生效的方法

字体大小: 中小 标准 ->行高大小: 标准

IBATIS的缓存证明还是比较简单的,思路如下:

首先,第一次查询时,从数据库中查询,得到结果.其次,在第二次查询之前,将数据库里的数据改变,再次进行查询.看结果如何.

结果一:查询结果跟第一次一直,缓存设置成功.

结果二:查询结果为更新后结果,缓存设置失败.

好了,话不多说直接上代码.至于jar包导入之类的就不再废话.

一、首先是建立一个简单的javabean,代码如下

package cn.itcast.beans;

import java.io.Serializable;
import java.sql.Date;

public class Student implements Serializable
{
    private int sid;
    private String sname;
    private String major;
    private Date birth;
    
    public int getSid()
    {
        return sid;
    }
    public void setSid(int sid)
    {
        this.sid = sid;
    }
    public String getSname()
    {
        return sname;
    }
    public void setSname(String sname)
    {
        this.sname = sname;
    }
    public String getMajor()
    {
        return major;
    }
    public void setMajor(String major)
    {
        this.major = major;
    }
    public Date getBirth()
    {
        return birth;
    }
    public void setBirth(Date birth)
    {
        this.birth = birth;
    }
    
    @Override
    public String toString()
    {
        String content = "sid="+sid+"\tsname="+sname+"\tmajor="+major+"\tbirth="+birth;
        // TODO Auto-generated method stub
        return content;
    }
    
}

二、然后是javabean对应的student.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE sqlMap 
        PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" 
        "http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace="Student">

    <!--模块配置-->
    <!--typeAlias节点: -->
    <!--
        定义了本映射文件中的别名,以避免过长变量值的反复书写,此例中通过
        typeAlias节点为类"cn.itcast.beans.Student"定义了一个别名"Student",
        这样在本配置文件的其他部分,需要引用"cn.itcast.beans.Student"类时,
         只需以其别名替代即可。
    -->
    <typeAlias alias="Student" type="cn.itcast.beans.Student"></typeAlias>
    <cacheModel id="userCache" type="LRU">
         <flushInterval hours="24"/> 
         <flushOnExecute statement="upateStudent"/> 
         <property name="size" value="1000" /> 
    </cacheModel>
    <!--Statement配置-->
    <select id="queryAllStudent" resultClass="Student" cacheModel="userCache">
        <![CDATA[ 
        select sid,sname,major,birth from student
        ]]>
    </select>
    <select id="selectStudentById" parameterClass="int" resultClass="Student" cacheModel="userCache">
    <![CDATA[ 
        select sid,sname,major,birth from student where sid=#sid#
        ]]>
    </select>
    <insert id="addStudent" parameterClass="Student">
    <![CDATA[ 
        insert into student(
        sname,
        major,
        birth
        )
        values(#sname#,#sname#,#birth#)
        ]]>
    </insert>
    <delete id="deleteStudent" parameterClass="int">
    <![CDATA[ 
        delete from student where sid=#sid#
        ]]>
    </delete>
    <update id="upateStudent" parameterClass="Student">
    <![CDATA[ 
        update Student
        set sname=#sname#,
            major=#major#,
            birth=#birth#
        where sid=#sid#
        ]]>
    </update>
    <select id="queryStudentByName" parameterClass="String"
        resultClass="Student">
    <![CDATA[ 
        select sid,sname,major,birth
          from student
         where sname like '%$sname$%'
         ]]>
    </select>
</sqlMap>

注意粗体部分是cacheModel相应的配置

三、SqlMapConfig.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMapConfig PUBLIC "-//ibatis.apache.org//DTD SQL Map Config2.0//EN" 
        "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
<sqlMapConfig>
    <properties resource="sqlMap.properties" />

    <!--cacheModelsEnabled  是否启用SqlMapClient上的缓存机制。建议设为"true" -->
    <!--
        enhancementEnabled 是否针对POJO启用字节码增强机制以提升getter/setter的调用效能,
        避免使用JavaReflect所带来的性能开销。同时,这也为Lazy Loading带来了极大的性能提升。建议设为"true"
    -->
    <!--errorTracingEnabled 是否启用错误日志,在开发期间建议设为"true"以方便调试 -->
    <!--lazyLoadingEnabled  是否启用延迟加载机制,建议设为"true" -->
    <!--maxRequests          最大并发请求数(Statement并发数) -->
    <!--maxTransactions      最大并发事务数 -->
    <!--
        maxSessions 最大Session数。即当前最大允许的并发SqlMapClient数。
        maxSessions设定必须介于maxTransactions和maxRequests之间,
        即maxTransactions<maxSessions=<maxRequests
    -->
    <!--
        useStatementNamespaces
        是否使用Statement命名空间。这里的命名空间指的是映射文件中,sqlMap节点的namespace属性,
        如在本例中针对student表的映射文件sqlMap节点: <sqlMap namespace="Student">
        这里,指定了此sqlMap节点下定义的操作均从属于"才tudent"命名空间。
        在useStatementNamespaces="true"的情况下,Statement调用需追加命名空间,
        如:sqlMapClient.update("Student.upateStudent", student);
        否则直接通过Statement名称调用即可,如:sqlMapClient.update("upateStudent", student);
        但请注意此时需要保证所有映射文件中,Statement定义无重名。
    -->
    <settings cacheModelsEnabled="true" enhancementEnabled="true"
        lazyLoadingEnabled="true" errorTracingEnabled="true" maxRequests="32"
        maxSessions="10" maxTransactions="5" useStatementNamespaces="false" />
    <!--transactionManager节点 -->
    <!--transactionManager节点定义了ibatis的事务管理器,目前提供了以下几种选择:
        Ø  JDBC     通过传统JDBC Connection.commit/rollback实现事务支持。
        Ø  JTA         使用容器提供的JTA服务实现全局事务管理。
        Ø EXTERNAL 外部事务管理,如在EJB中使用ibatis,通过EJB的部署配置即可实现自动的事务管理机制。
        此时ibatis将把所有事务委托给外部容器进行管理。此外,通过Spring等轻量级容器实现
        事务的配置化管理也是一个不错的选择。关于结合容器实现事务管理,参见“高级特性”中的描述。
    -->
    <transactionManager type="JDBC">
        <!--dataSource节点 -->
        <!--
            dataSource从属于transactionManager节点,用于设定ibatis运行期使用的DataSource属性。
            type属性: dataSource节点的type属性指定了dataSource的实现类型。
            可选项目:
            Ø SIMPLE:
            SIMPLE是ibatis内置的dataSource实现,其中实现了一个简单的 数据库连接池机制,对应 ibatis 实现类为
            com.ibatis.sqlmap.engine.datasource.SimpleDataSourceFactory。
            Ø DBCP:
            基于Apache DBCP连接池组件实现的DataSource封装,当无容器提 供DataSource
            服务时,建议使用该选项,对应ibatis 实现类为
            com.ibatis.sqlmap.engine.datasource.DbcpDataSourceFactory。
            Ø JNDI:
            使用J2EE容器提供的DataSource实现,DataSource将通过指定 的 JNDI Name 从容器中获取。对应 ibatis实现类为 
            com.ibatis.sqlmap.engine.datasource.JndiDataSourceFactory。
        -->
        <dataSource type="SIMPLE">
            <property value="${driver}" name="JDBC.Driver" />
            <property value="${url}" name="JDBC.ConnectionURL" />
            <property value="${username}" name="JDBC.Username" />
            <property value="${password}" name="JDBC.Password" />
        </dataSource>
    </transactionManager>
    <sqlMap resource="cn/itcast/beans/Student.xml" />
</sqlMapConfig>

四、sqlMap.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql:///ibatis
username=root
password=root

五、接口

package cn.itcast.dao;



import java.util.List;

import cn.itcast.beans.Student;

public interface IstudentDao
{
    public void addStudent(Student student);
    public void deleteStudent(int id);
    public void upateStudent(Student student);
    public List<Student> queryAllStudent();
    public List<Student> queryStudentByName(String name);
    public Student queryStudentById(int id);
    
}

六、接口实现类

package cn.itcast.dao.impl;

import java.io.IOException;
import java.io.Reader;
import java.sql.Date;
import java.sql.SQLException;
import java.util.List;

import com.ibatis.common.resources.Resources;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapClientBuilder;
import com.ibatis.sqlmap.engine.mapping.sql.Sql;

import cn.itcast.beans.Student;
import cn.itcast.dao.IstudentDao;

public class IstudentDaoIbatisImpl implements IstudentDao
{
    private static SqlMapClient sqlMapClient;
    /**
     * 这部分内容应该说是最重要的主要作用是读取配置文件
     * 通过配置文件中的信息进行一系列的操作得到sqlMapClient对象
     * 最后要关闭字符输入流
     */
    static
    {
        try
        {
            //读取SqlMapConfig.xml文件
            Reader reader = Resources.getResourceAsReader("SqlMapConfig.xml");
            sqlMapClient = SqlMapClientBuilder.buildSqlMapClient(reader);
            reader.close();
        }
        catch (IOException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    public void addStudent(Student student)
    {
        try
        {
            /**
             * 当Student.xml中<sqlMap namespace="Student">,且SqlMapConfig.xml中setting节点设置了useStatementNamespaces="true"时,
             */
            //sqlMapClient.insert("Student.addStudent", student);
            sqlMapClient.insert("addStudent", student);
        }
        catch (SQLException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    public void deleteStudent(int id)
    {
        
        try
        {
            int i = sqlMapClient.delete("deleteStudent", id);
            System.out.println(i);
        }
        catch (SQLException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }

    public List<Student> queryAllStudent() 
    {
        List<Student> students = null;
        try
        {
            students = sqlMapClient.queryForList("queryAllStudent");
        }
        catch (SQLException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return students;
    }

    public Student queryStudentById(int id)
    {
        Student student = null;
        try
        {
            student = (Student) sqlMapClient.queryForObject("selectStudentById", id);
        }
        catch (SQLException e)
        {
            e.printStackTrace();
        }
        return student;
    }

    public void upateStudent(Student student)
    {
        try
        {
            int i = sqlMapClient.update("upateStudent", student);
            System.out.println(i);
        }
        catch (SQLException e)
        {
            e.printStackTrace();
        }
    }
    
    public List<Student> queryStudentByName(String name)
    {
        List<Student> students = null;
        try
        {
            students = sqlMapClient.queryForList("queryStudentByName", name);
        }
        catch (SQLException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return  students;
    }
    
    public static void main(String[] args)
    {
        IstudentDao dao = new IstudentDaoIbatisImpl();
/**        queryAllStudent
         List<Student> students =dao.queryAllStudent();
         for(Student student: students)
         {
             System.out.println(student);
         }
     System.out.println(students);
 */    
        
/**        queryStudentById
         Student student = dao.queryStudentById(2);
         System.out.println(student);
 */    
        
/**        addStudent
        Student student = new Student();
        student.setSname("houjinxin");
        student.setMajor("电信");
        student.setBirth(Date.valueOf("2012-01-14"));
        dao.addStudent(student);
        System.out.println("插入成功");
*/        
        
/**        deleteStudent
          dao.deleteStudent(2);
        System.out.println("删除成功!");
 */
/**        updateStudent
        Student student = new Student();
        student.setSid(3);
        student.setSname("houjinxin");
        student.setMajor("电信08");
        student.setBirth(Date.valueOf("2012-01-14"));
        dao.upateStudent(student);
 */
        
        
      Student student = null;
student = dao.queryStudentById(2); System.out.println(student); student = dao.queryStudentById(2
); System.out.println(student); } }

注意红色代码部分即为测试代码,终于把他沾出来了。

我的方法是这样,在第二个student前打个断点,然后用debug模式启动,执行到断点处打印一次查询的结果,结果如下

sid=2    sname=woshiou    major=houjinxin    birth=2012-01-14

然后后到数据库中改变所查的记录,如图所示:

继续执行刚才的代码直至结束.结果如下

sid=2    sname=woshiou    major=houjinxin    birth=2012-01-14
sid=2    sname=woshiou    major=houjinxin    birth=2012-01-14

可以看到,虽然数据库改变了但是查询到的结果,仍然没有改变,所以缓存设置成功。

还要注意一点,验证缓存是否成功的关键是一定要在同一个连接未关闭前验证 ,如果上例改成

    Student student = null;
    student = dao.queryStudentById(2);
     System.out.println(student);

只有一次查询,让他执行两次,那么数据库中是什么,查到的就是什么.就无法检验出缓存是否配置成功。

此文章由 http://www.ositren.com 收集整理 ,地址为: http://www.ositren.com/htmls/68645.html