<parameterMap
id="parameterMapName" [class="Author"]>
<parameter property ="propertyName"
[jdbcType="VARCHAR"] [javaType="string"]
[nullValue="NUMERIC"]
[null="-9999999"]/>
<parameter …… />
<parameter …… />
</parameterMap>
括号[]中是可选的属性。parameterMap 元素的id 属性作为唯一标识,在同一个SQL Map XML 文件中不能重名。一个parameterMap 可包含任意多的property 元素。
property属性是指传入mapped statement中的JavaBean参数对象的属性名。这个属性名可以使用多次,这要看在这个statement中,这个属性名要出现多少次。例如:
<parameterMap
id="authorParameter3" class="Author">
<parameter property="name"
jdbcType="VARCHAR" javaType="java.lang.String" mode="INOUT"/>
<parameter property="name"
jdbcType="VARCHAR" javaType="java.lang.String" mode="INOUT"/>
</parameterMap>
<update
id="updateAuthor2" parameterMap="authorParameter2">
UPDATE author set auth_name=? WHERE
auth_name = ?
</update>
但是如果使用这样的方法的话,调用代码应该是:
Author author =
new Author();
author.setName("作者三");
sqlMapClient.update("updateAuthor2", paraMap);
那么它其实执行的是:
UPDATE author set auth_name='作者三' WHERE auth_name = '作者三'
这样的话,就根本没有了意义,因为,你只能传进一个Author对象,而这个Author对象的name属性值将会被用在整个Sql语句中,而一般的情况下是不应该相同的,也就是说,我们的本意可能是想:
UPDATE author set auth_name='作者N' WHERE auth_name = '作者三'
方法倒是有,不过我觉得不太好。
<parameterMap
id="authorParameter2" class="java.util.HashMap">
<parameter property="name1"
jdbcType="VARCHAR" javaType="java.lang.String" mode="INOUT"/>
<parameter property="name2"
jdbcType="VARCHAR" javaType="java.lang.String" mode="INOUT"/>
</parameterMap>
<update
id="updateAuthor2" parameterMap="authorParameter2">
UPDATE author set auth_name=? WHERE
auth_name = ?
</update>
调用代码为:
HashMap paraMap =
new HashMap();
paraMap.put("name1", "作者N");
paraMap.put("name2", "作者三");
sqlMapClient.update("updateAuthor2", paraMap);
如果你想到更好的方法解决这个问题的话,请不吝赐教。
jdbcType用于指明数据库的字段类型。如果不说明字段类型的话,一些JDBC驱动程序就无法确定要操作的字段类型。例如:PreparedStatement.setNull(int parameterIndex, int
sqlType)方法,要求指定数据类型。如果不指定数据类型,某些Driver 可能指定为Types.Other 或Types.Null。但是,不能保证所有的Driver 都表现一致。对于这种情况,SQL Map API 允许使用parameterMap 元素的jdbcType 属性指定数据类型。
正常情况下,只有当字段可以为NULL或日期时间类型时才需要type 属性。因为Java 只有一个Date 类型(java.util.Date),而大多数SQL 数据库有多个-通常至少有3 种。因此,需要指定字段类型是DATE 还是DATETIME。
Type 属性可以是JDBC Types 类中定义的任意参数的字符串值。虽然如此,还是有某些类型不支持(即BLOB)。
注意!大多数JDBC Driver 只有在字段可以为NULL 时需要指定type 属性。因此,对于这些Driver,只是在字段可以为NULL 时才需要指定type 属性。
注意!当使用Oracle Driver 时,如果没有给可以为NULL 的字段指定type 属性,当试图给这些字段赋值NULL 时,会出现"Invalid column。 type"错误。
javaType用于指明作为参数传递的java bean的属性的类型。通常情况下,这可以通过反射机制从java bean中获取类型,但是一些特定的映射,比如说MAP和XML的映射就无法将类型信息传递给框架了。如果java type没有设置而且框架无法获知类型的话,那么这个类型会被指定为Object。
属性 nullValue的值可以是对于property 类型来说合法的任意值,用于指定NULL 的替换值。就是说,当Java Bean的属性值等于指定值时,相应的字段将赋值NULL。这个特性允许在应用中给不支持null的数据类型(即int,double,float等)赋值null。当这些数据类型的属性值匹配nullValue值(即匹配-9999)时,NULL 将代替nullValue 值写入数据库。
例如:
<parameterMap
id="authorParameter" class="Author">
<parameter property="name"
jdbcType="VARCHAR" javaType="java.lang.String" nullValue="NO_ENTRY"
mode="INOUT"/>
<parameter property="age"
jdbcType="INTEGER" javaType="java.lang.Integer" nullValue="-999"
mode="INOUT"/>
<parameter property="telephone"
jdbcType="VARCHAR" javaType="java.lang.String" nullValue="NO_ENTRY"
mode="INOUT"/>
<parameter
property="address" jdbcType="VARCHAR" javaType="java.lang.String"
nullValue="NO_ENTRY" mode="INOUT"/>
</parameterMap>
<insert
id="insertAuthor1" parameterMap="authorParameter">
INSERT INTO author
(auth_name,auth_age,auth_tel,auth_address) VALUES (?,?,?,?)
</insert>
您可以在另一个SQL Map XML 文件中引用parameterMap。例如,要在另一个文件中引用上面的parameterMap,可以使用名称"Product.insert-product-param"。
使用Inline Parameter Maps,可以把Java Bean 的属性名称嵌在mapped-statement 的定义中(即直接写在SQL 语句中)。
例如:
<insert
id="insertAuthor1" parameterClass="Author">
INSERT INTO author
(auth_name,auth_age,auth_tel,auth_address) VALUES
(#name#,#age#,#telephone#,#address#)
</insert>
这样,在你的Author类中,要有name,age,telephone,address的属性以及相应的get和set方法,这样做可以避免使用另外定义parameterMap的麻烦。
你也可以在内嵌参数中指定数据类型和nullValue,例如:
<insert
id="insertAuthor1" parameterClass="Author">
INSERT INTO author
(auth_name,auth_age,auth_tel,auth_address) VALUES
(#name:VARCHAR:NO_ENTRY#,#age:INTEGER:-999#,#telephone:VARCHAR:NO_ENTRY#,#address:VARCHAR:NO_ENTRY#)
</insert>
注意!在内嵌参数中,要指定NULL 的替代值,必须要先指定数据类型。
注意!如需要在查询时也使用NULL 替代值,必须同时在resultMap 中定义。
注意!如果您需要指定很多的数据类型和NULL 替代值,可以使用外部的parameterMap元素,这样会使代码更清晰。
在SQL Map 架构中,Result Map 是极其重要的组件。在执行查询Mapped Statement 时,resultMap 负责将结果集的列值映射成Java Bean 的属性值。resultMap 的结构如下:
<resultMap
id="resultMapName" class="some.domain.Class"
[extends="parent-resultMap"]>
<result property="propertyName"
column="COLUMN_NAME"
[columnIndex="1"] [javaType="int"]
[jdbcType="NUMERIC"]
[nullValue="-999999"]
[select="someOtherStatement"]
/>
<result ……/>
<result ……/>
<result ……/>
</resultMap>
括号[]中是可选的属性resultMap 也有class 属性,是Java 类的全限定名(即包括包的名称)或该类的别名。该Java 类初始化并根据定义填充数据。
Extends 是可选的属性,可以设定成以为基础的另外一个resultMap 的名字。和在Java 中继承一个类相似,父resultMap 的属性将作为子resultMap 的一部分。父resultMap 的属性总是加到子resultMap 属性的前面,并且父resultMap 必须要在子resultMap 之前定义。父resultMap 和子resultMap 的class 属性不一定要一致,它们可以没有任何关系。
resultMap 可以包括任意多的property 映射,将查询结果集的列值映射成Java Bean 的属性。属性的映射按它们在resultMap中定义的顺序进行。属性class 必须符合Java Bean 规范,每一属性都必须拥有get/set 方法。
注意!ResultSet 的列值按它们在resultMap 中定义的顺序读取。
property属性是指从mapped statement中返回的JavaBean对象的属性名。这个属性名也可以使用多次。
column属性值是ResultSet中的列名字,即字段名,取得的这个字段的值将赋给property所指的bean属性。
可选属性,用于改善性能。属性columnIndex 的值是ResultSet 中用于赋值Java Bean属性的字段次序号。在99%的应用中,不太可能需要牺牲可读性来换取性能。使用columnIndex,某些JDBC Driver可以大幅提高性能,某些则没有任何效果。
同ParameterMap中的jdbcType
同ParameterMap中的javaType
属性nullValue指定数据库中NULL的替代值。因此,如果从ResultSet中读出NULL值,JavaBean属性将被赋值为属性nullValue指定的替代值。
如果数据库中存在NULLABLE 属性的字段,但您想在你的应用程序中用指定的常量代替NULL,您可以这样做:
<resultMap
id="get-product-result" class="Author">
<result property="id"
column="auth_id"/>
<result property="age"
column="auth_age"/>
<result property="name"
column="auth_name" nullValue="you have no name"/>
</resultMap>
在上例中,如果取得的记录中auth_name字段的值为NULL,那么在赋给java bean的时候,name属性将被赋为"you have no name"。
如果在一个类与另一个类之间是关联关系的话,那么当你用JDBC取得记录的时候,这个关联关系是如何实现的呢?例如这样的关系:一个作者可能会有多个文章发表,那么作者与文章之间就是很强的关联关系,而且是一对多的关系,在Author的Bean中是这样写的:
public class
Author
{
private int id;
.....
private List articleList;
public int getId()
{
return id;
}
public void setId(int id)
{
this.id=id;
}
... ...
public List getArticleList()
{
return articleList;
}
public void setArticleList(List
articleList)
{
this.articleList=articleList;
}
}
当你执行一条sql语句从数据表author中取出相应的数据的时候,在上面的java bean中,articleList如何赋值呢?这时候,就需要使用select属性。
1.1:1关系:
我们先假设在author和article之间使用1:1的关系,虽然在真实世界中是不正确的,我们只是做个例子,那么Author和article的bean代码如下:
public class
Author
{
private int id;
private int age;
private String name;
private String address;
private String telephone;
private Article article;
public int getId()
{
return id;
}
public void setId(int id)
{
this.id=id;
}
public int getAge()
{
return age;
}
public void setAge(int age)
{
this.age=age;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name=name;
}
public String getAddress()
{
return address;
}
public void setAddress(String
address)
{
this.address=address;
}
public String getTelephone()
{
return telephone;
}
public void setTelephone(String
telephone)
{
this.telephone=telephone;
}
public Article getArticle()
{
return this.article;
}
public void setArticle(Article
article)
{
this.article=article;
}
}
public class
Article
{
private int id;
private String title;
private Date createtime;
private int author;
public int getId()
{
return id;
}
public void setId(int id)
{
this.id=id;
}
public String getTitle()
{
return title;
}
public void setTitle(String
title)
{
this.title=title;
}
public Date getCreatetime()
{
return createtime;
}
public void setCreatetime(Date
createtime)
{
this.createtime=createtime;
}
public int getAuthor()
{
return author;
}
public void setAuthor(int
author)
{
this.author=author;
}
}
在author.xml的配置如下:
<resultMap
id="linkResultMap1" class="Author">
<result property="id"
column="auth_id"/>
<result property="age"
column="auth_age"/>
<result property="name"
column="auth_name"/>
<result property="telephone"
column="auth_tel"/>
<result property="address"
column="auth_address"/>
<result property="article"
column="auth_id" select="getLinkArticle1"/>
</resultMap>
<select
id="getAuthor5" resultMap="linkResultMap1" parameterClass="int">
SELECT * FROM author WHERE auth_id =
#id#
</select>
<select
id="getLinkArticle1" resultClass="com.ibatis.beans.Article"
parameterClass="int">
SELECT art_id as id,art_title as
title,art_createtime as createtime,art_author as author FROM article WHERE
art_id = #id#
</select>
调用代码如下:
Author author = (Author)sqlMapClient.queryForObject("getAuthor5", new
Integer(1));
System.out.println(author.getName()+"'s article is
:"+author.getArticle().getTitle());
你可以看到,对于Author类中的article属性,IBatis是将取得的记录的auth_id字段值作为参数传入到id="getLinkArticle1"的语句中,并将取得的结果封装成Article对象,并赋给Author的article属性。上面的调用代码实际执行的两条sql语句是:
SELECT * FROM
author WHERE auth_id = 1
SELECT art_id as
id,art_title as title,art_createtime as createtime,art_author as author FROM
article WHERE art_id = 1
在第二条语句中,将取得的记录封装成Article对象,并赋给Author的article属性,所以,你可以直接使用author.getArticle().getTitle()获得文章的标题。
上面的方法显示了如何实现1:1的关联关系,但是上面的方法并不好,原因是可能会执行很多次查询!
(1)避免 N+1 Selects (1:1)
如果上面的配置如下:
<resultMap
id="linkResultMap1" class="Author">
<result property="id"
column="auth_id"/>
<result property="age"
column="auth_age"/>
<result property="name"
column="auth_name"/>
<result property="telephone"
column="auth_tel"/>
<result property="address"
column="auth_address"/>
<result property="article"
column="auth_id" select="getLinkArticle1"/>
</resultMap>
<select
id="getAuthor5" resultMap="linkResultMap1" parameterClass="int">
SELECT * FROM author WHERE auth_id >
#id#
</select>
<select
id="getLinkArticle1" resultClass="com.ibatis.beans.Article"
parameterClass="int">
SELECT art_id as id,art_title as
title,art_createtime as createtime,art_author as author FROM article WHERE
art_id = #id#
</select>
调用代码如下:
Author author = (Author)sqlMapClient.queryForList("getAuthor5", new
Integer(1));
如果SELECT * FROM author WHERE auth_id > 1的记录有N条,那么将对id="getLinkArticle1"的语句执行N次查询,这样所有的查询总数将为N+1次,执行效率会很低。
这时,可以使用下面的联合查询的方法来解决:
<resultMap
id="linkResultMap2" class="Author">
<result property="id"
column="auth_id"/>
<result property="age"
column="auth_age"/>
<result property="name"
column="auth_name"/>
<result property="telephone"
column="auth_tel"/>
<result property="address"
column="auth_address"/>
<result property="article.title"
column="art_title"/>
</resultMap>
<select
id="getAuthor6" resultMap="linkResultMap2" parameterClass="int">
<![CDATA[ SELECT
a.auth_id,a.auth_age,a.auth_name,a.auth_tel,a.auth_address,b.art_title FROM
author a,article b WHERE a.auth_id > #id# and a.auth_id =
b.art_id]]>
</select>
调用代码为:
Author author =
(Author)sqlMapClient.queryForList("getAuthor6", new Integer(1));
这样只用一条Sql语句就可以解决。
2.1:M与M:N关系:
下面我们讨论1:M的关系,一个author可能有多个article,所以,author与article之间是一对多的关系。那么我们在Author类中加入如下代码(在省略号间的是要加入的代码):
public class
Author
{
... ...
private List articleList;
public List getArticleList()
{
return articleList;
}
public void setArticleList(List
articleList)
{
this.articleList=articleList;
}
... ...
}
配置如下:
<resultMap
id="linkResultMap3" class="Author">
<result property="id"
column="auth_id"/>
<result property="age"
column="auth_age"/>
<result property="name"
column="auth_name"/>
<result property="telephone"
column="auth_tel"/>
<result property="address"
column="auth_address"/>
<result property="articleList"
column="auth_id" select="getLinkArticle3"/>
</resultMap>
<select
id="getAuthor7" resultMap="linkResultMap3" parameterClass="int">
SELECT * FROM author WHERE auth_id =
#id#
</select>
<select
id="getLinkArticle3" resultClass="com.ibatis.beans.Article"
parameterClass="int">
SELECT art_id as id,art_title as
title,art_createtime as createtime,art_author as author FROM article WHERE
art_author = #id#
</select>
调用代码为:
Author author =
(Author)sqlMapClient.queryForObject("getAuthor7", new Integer(1));
System.out.println(author.getName()+"的文章有:");
for(int
i=0;i<author.getArticleList().size();i++)
{
int num=i+1;
Article art =
(Article)author.getArticleList().get(i);
System.out.println(num+".
"+art.getTitle());
}
从上面的实现可以看出,你只需要在bean中加入一个java.util.List(或java.util.Collection)类型的articleList来表示所有的文章列表即可,调用部分没有什么变化,IBaits会自动从Article中取得的记录封装成Article对象并加入到一个List对象中,然后将这个List对象赋值给Author类的articleList属性。
(1)避免 N+1 Selects (1:M and M:N)
1:M和M:N的情况与1:1的情况相似,也会出现N+1 Selects 的情况,但是到目前位置,还没有其他的方法来解决这个问题,希望在不久的将来能够解决。
3.多个复杂参数属性
你可能已经注意到了,上面的例子中,在resultMap中只指明了一个column属性用于id=”getLinkArticle”的statement关联。其实,Ibatis允许你指明多个column属性与id=”getLinkArticle”的statement关联,语法很简单, {param1=column1,
param2=column2, …, paramN=columnN}。下面是一个例子:
<resultMap
id="linkResultMap4" class="Author">
<result property="id"
column="auth_id"/>
<result property="age"
column="auth_age"/>
<result property="name"
column="auth_name"/>
<result property="telephone"
column="auth_tel"/>
<result property="address"
column="auth_address"/>
<result property="articleList"
column="{id=auth_id,address=auth_address}"
select="getLinkArticle4"/>
</resultMap>
<select
id="getAuthor8" resultMap="linkResultMap4" parameterClass="int">
SELECT * FROM author WHERE auth_id =
#id#
</select>
<select
id="getLinkArticle4" resultClass="com.ibatis.beans.Article"
parameterClass="int">
SELECT art_id as id,art_title as
title,art_createtime as createtime,art_author as author FROM article WHERE
art_author = #id# and art_publish_add=#address#
</select>
你也可以只写字段的名称,只要按照所关联的statement中所对应的字段顺序即可,象这样:
{auth_id,auth_address}
上面的这个例子我在Mysql的环境中运行没有通过,报出的错误是:Column'{auth_id,auth_address}'
not found.
这个错误是与JDBC驱动无关的,而是在做XML解析的时候发生的错误,不知道是什么原因,如果您有这样的成功经历的话,希望能共同分享,我的Email是:[email protected]
注意:有些JDBC驱动不支持同时打开多个ResultSets(单个连接)。所以说,这样的驱动不能完成复杂对象的映射,因为JDBC驱动需要多个ResultSets的连接,这时候,只能使用一个关联查询解决问题。
如果你使用Microsoft
SQL Server 2000 的JDBC驱动的话,你需要在配置url的时候,在url后加上SelectMethod=Cursor。
4.在Parameter Maps and Result
Maps中支持的参数
Java Type |
JavaBean/Map
Property
Mapping |
Result Class
/
Parameter
Class*** |
Type
Alias** |
boolean |
YES |
NO |
boolean |
java.lang.Boolean |
YES |
YES |
boolean |
byte |
YES |
NO |
byte |
java.lang.Byte |
YES |
YES |
byte |
short |
YES |
NO |
short |
java.lang.Short |
YES |
YES |
short |
int |
YES |
NO |
Int/
Integer |
java.lang.Integer |
YES |
YES |
Int/
Integer |
long |
YES |
NO |
long |
java.lang.Long |
YES |
YES |
long |
float |
YES |
NO |
float |
java.lang.Float |
YES |
YES |
float |
double |
YES |
NO |
double |
java.lang.Double |
YES |
YES |
double |
java.lang.String |
YES |
YES |
string |
java.util.Date |
YES |
YES |
date |
java.math.BigDecimal |
YES |
YES |
decimal |
*
java.sql.Date |
YES |
YES |
N/A |
*
java.sql.Time |
YES |
YES |
N/A |
*
java.sql.Timestamp |
YES |
YES |
N/A |
<cacheModel
id="product-cache" type ="LRU" readOnly=”true”
serialize=”false”>
<flushInterval
hours="24"/>
<flushOnExecute
statement="insertProduct"/>
<flushOnExecute
statement="updateProduct"/>
<flushOnExecute
statement="deleteProduct"/>
<property
name=”cache-size” value=”1000” />
</cacheModel>
上面的cache model 创建了一个名为“product-cache”的缓存,使用“最近最少使用”(LRU)实现,每24小时,缓冲区将刷新一次,而且在执行insertProduct、updateProduct和deleteProduct的statement时,缓冲区也将刷新,设定的时间可以设定为hours,
minutes, seconds 或
milliseconds。一些Cache的实现需要附加的属性,比如说上例中的cache-size
属性,cache的大小指明了可以存放在cache中的实体的个数。type属性的名称要么是全限定的类名,要么是缓存实现的别名。Cache Model 使用插件的形式来支持不同的缓存算法。它的实现在cache-model 元素的type属性中指定(如上所示)。
(一)Read-Only 与 Read/Write
Ibatis支持只读和可读写的Cache,只读的Cache可以在所有的用户间共享,所以它可以提供更大的操作空间。但是从只读缓冲中读取的对象不能够被修改。如果你要对你取得的对象进行修改的话,那么你只能用可读写的缓冲。readOnly=”true”为只读缓冲;readOnly=”false”为可读写缓冲。
(二)Serializable Read/Write
Caches
要使用Serializable Read/Write
Caches,设置readOnly=”false”, serialize=”true”。默认情况下,采用的是readOnly=”
true”, serialize=”false”。
目前包括以下的4 个缓冲类型实现:
1. “MEMORY” (com.ibatis.db.sqlmap.cache.memory.MemoryCacheController)
MEMORY cache 实现使用reference 类型来管理cache 的行为。垃圾收集器可以根据reference 类型判断是否要回收cache 中的数据。MEMORY 实现适用于没有统一的对象重用模式的应用,或内存不足的应用。
MEMORY 实现可以这样配置:
<cache-model name="product-cache" implementation
="MEMORY">
<flush-interval hours="24"/>
<flush-on-execute statement="insertProduct"/>
<flush-on-execute statement="updateProduct"/>
<flush-on-execute statement="deleteProduct"/>
<cache-property name=”reference-type” value=”WEAK” />
</cache-model>
MEMORY cache 实现只认识一个<cache-property>元素。这个名为“reference-type”属性的值必须是STRONG,SOFT 和WEAK 三者其一。这三个值分别对应于JVM 不同的内存reference 类型。
(1) WEAK(缺省)
大多数情况下,WEAK类型是最佳选择。如果不指定类型,缺省类型就是WEAK。它能大大提高常用查询的性能。但是对于当前不被使用的查询结果数据,将被清除以释放内存用来分配其他对象。
(2) SOFT
在查询结果对象数据不被使用,同时需要内存分配其他对象的情况下,SOFT类型将减少内存不足的可能性。然而,这不是最具侵入性的reference类型,结果数据依然可能被清除。
(3) STRONG
确保查询结果数据一直保留在内存中,除非Cache被刷新(例如,到了刷新的时间或执行了更新数据的操作)。
对于下面的情况,这是理想的选择:
1”
结果内容数据很少
2”
完全静态的数据
3”
频繁使用的数据
优点是对于这类查询性能非常好。缺点是,如果需要分配其他对象,内存无法释放(可能是更重要的数据对象)。
2. “LRU”
(com.ibatis.db.sqlmap.cache.lru.LruCacheController)
LRU Cache 实现用“最近最少使用”原则来确定如何从Cache 中清除对象。当Cache溢出时,最近最少使用的对象将被从Cache 中清除。
<cache-model name="product-cache" implementation
="LRU">
<flush-interval hours="24"/>
<flush-on-execute statement="insertProduct"/>
<flush-on-execute statement="updateProduct"/>
<flush-on-execute statement="deleteProduct"/>
<cache-property name=”cache-size” value=”1000” />
</cache-model>
值得注意的是,这里指的对象可以是任意的,从单一的String 对象到Java Bean 的ArrayList 对象都可以。因此,不要Cache 太多的对象,以免内存不足。
3. “FIFO”
(com.ibatis.db.sqlmap.cache.fifo.FifoCacheController)
FIFO Cache 实现用“先进先出”原则来确定如何从Cache 中清除对象。对于短时间内持续引用特定的查询而后很可能不再使用的情况,FIFO Cache 是很好的选择。
<cache-model name="product-cache" implementation
="FIFO">
<flush-interval hours="24"/>
<flush-on-execute statement="insertProduct"/>
<flush-on-execute statement="updateProduct"/>
<flush-on-execute statement="deleteProduct"/>
<cache-property name=”cache-size” value=”1000” />
</cache-model>
值得注意的是,这里指的对象可以是任意的,从单一的String 对象到Java Bean 的ArrayList 对象都可以。因此,不要Cache 太多的对象,以免内存不足。
4. “OSCACHE”
(com.ibatis.db.sqlmap.cache.oscache.OSCacheController)
OSCACHE Cache 实现是OSCache2.0 缓存引擎的一个Plugin。它具有高度的可配置性,分布式,高度的灵活性。
<cache-model name="product-cache" implementation
="OSCACHE">
<flush-interval hours="24"/>
<flush-on-execute statement="insertProduct"/>
<flush-on-execute statement="updateProduct"/>
<flush-on-execute statement="deleteProduct"/>
</cache-model>
OSCACHE 实现不使用cache-property 元素。而是在类路径的根路径中使用标准的oscache.properties 文件进行配置。在oscache.properties 文件中,您可以配置Cache 的算法(和上面讨论的算法很类似),Cache 的大小,持久化方法(内存,文件等)和集群方法。
要获得更详细的信息,请参考OSCache 文档。OSCache 及其文档可以从OpenSymphony网站上获取:http://www.opensymphony.com/oscache/