您的位置:首页 > 其它

证明IBATIS缓存生效的方法

2012-05-11 15:34 405 查看
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);


只有一次查询,让他执行两次,那么数据库中是什么,查到的就是什么.就无法检验出缓存是否配置成功。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: