【转】笑着学习笔记iBatis入门

根据官网上的开发指南,按照个人使用习惯,频度等整理的,没啥特别的东西。

笑着--胖胖兰学iBatis

一,       iBatis简介

iBatis是一种数据库持续层的ORM框架。使用简单的XML配置文件将Java Bean映射成PreparedStatement的输入参数和ResultSet结果集

 

在不是很复杂的情况下,我们 甚至可以使用HashMap而不是Java Bean来映射PreparedStatement的输入参 数和ResultSet结果集,从而节省开发时间与成本。 或者,我们可以使用一些辅助工具来帮助我们通过XML配置生成对应的Java Bean.

 

 

 

 

 

 

 

 

 

二,       iBatis工作原理,流程

iBatis使用简单的XML描述文件将Java BeanMap实现和基本数据类型的包装类(StringInteger等)映射成JDBCPreparedStatement的输入参数 和ResultSet结果集。具体工作流程如下:

 

1.在sqlMapConfigXML配置文件中进行数据库连接的配 置,XML配置文件名称任意,比如sql-map-config.xml

2sqlMapConfigXML配置文件中引用sqlMapXML配置文件

<sqlMap resource="examples/sqlmap/maps/Person1.xml" />

<sqlMap url="file:///c:/config/Customer.xml " />

3.在sqlMapXML配置文件中进行SQL文的配置,文件名称任意, 比如Person1.xml

4.通过SqlMapClientBuilder生成具体的操作sqlMap配置文件中SQL文的 IBATIS对象SqlMapClient

String resource = "config/ibatis/sql-map-config.xml";                  

Reader reader = Resources.getResourceAsReader (resource);                      

SqlMapClient sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);

5SqlMapClient对象提供函数,函数的参数 对应替换sqlMap配置文件中的id,parameter等等属性,完成SQL文的执 行。具体参照iBatisAPI

public List queryForList(String statementName, Object parameterObject,

int skipResults, int maxResults)

statement:sqlMap配置中id属性,parameterObject:sqlMap配置中parameterXXX属性

 

 

iBatis的工作重点在于配置文件的 做成上,尤其sqlMap配置文件的做成是我们需要重点学习的。

 

 

 

 

 

 

 

 

三,       SqlMapConfig.xml

配置例子如下,各个标签的说 明参考官方文档。比较容易理解,这里不做整理

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

<!DOCTYPE sqlMapConfig

PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"

"http://www.ibatis.com/dtd/sql-map-config-2.dtd">

<sqlMapConfig>

<properties resource=" examples/sqlmap/maps/SqlMapConfigExample.properties " />

<settings

cacheModelsEnabled="true"

enhancementEnabled="true"

lazyLoadingEnabled="true"

maxRequests="32"

maxSessions="10"

maxTransactions="5"

useStatementNamespaces="false"

/>

<typeAlias alias="order" type="testdomain.Order"/>

<transactionManager type="JDBC" >

<dataSource type="SIMPLE">

<property name="JDBC.Driver" value="${driver}"/>

<property name="JDBC.ConnectionURL" value="${url}"/>

<property name="JDBC.Username" value="${username}"/>

<property name="JDBC.Password" value="${password}"/>

<property name="JDBC.DefaultAutoCommit" value="true" />

<property name="Pool.MaximumActiveConnections" value="10"/><property name="Pool.MaximumIdleConnections" value="5"/>

<property name="Pool.MaximumCheckoutTime" value="120000"/>

<property name="Pool.TimeToWait" value="500"/>

<property name="Pool.PingQuery" value="select 1 from ACCOUNT"/>

<property name="Pool.PingEnabled" value="false"/>

<property name="Pool.PingConnectionsOlderThan" value="1"/>

<property name="Pool.PingConnectionsNotUsedFor" value="1"/>

</dataSource>

</transactionManager>

<sqlMap resource="examples/sqlmap/maps/Person.xml" />

<sqlMap url="file:///c:/config/Customer.xml " />

</sqlMapConfig>

 

以上,主要注意DB连接情报的配置方法,采用 了Java的标准Properties文件。

<properties resource=" examples/sqlmap/maps/SqlMapConfigExample.properties " />

       然后在XML中引用properties文 件中的定义。

           <property name="JDBC.Driver" value="${driver}"/>

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

四,       SqlMap.xml总体印象

较复杂的例子:

<sqlMap id=”Product”>

<cacheModel id=”productCache” type=”LRU”>

<flushInterval hours=”24”/>

<property name=”size” value=”1000” />

</cacheModel>

<typeAlias alias=”product” type=”com.ibatis.example.Product” />

<parameterMap id=”productParam” class=”product”>

<parameter property=”id”/>

</parameterMap>

<resultMap id=”productResult” class=”product”>

<result property=”id” column=”PRD_ID”/>

<result property=”description” column=”PRD_DESCRIPTION”/>

</resultMap>

<select id=”getProduct” parameterMap=”productParam”

resultMap=”productResult” cacheModel=”product-cache”>

select * from PRODUCT where PRD_ID = ?

</select>

</sqlMap>

 

      以上例子简化版:

<sqlMap id=”Product”>

<select id=”getProduct” parameterClass=” com.ibatis.example.Product”

resultClass=”com.ibatis.example.Product”>

Select

PRD_ID as id,

PRD_DESCRIPTION as description

From PRODUCT

Where PRD_ID = #id#

</select>

</sqlMap>

 

五,       Statement语法,类型,及其属性和特点

1.语法

<statement

 id=”statementName”

[parameterClass=”some.class.Name”]

[resultClass=”some.class.Name”]

[parameterMap=”nameOfParameterMap”]

[resultMap=”nameOfResultMap”]

[cacheModel=”nameOfCache”]

>

select * from PRODUCT where PRD_ID = [?|#propertyName#] order by [$simpleDynamic$]

</statement>

 

[]内 为可选项,不是必须存在的。

 

2.Statement类型,属性,特点

六,       关于映射时输入值的匹配问题

1.     SqlMapClient如何从SqlMap的配置文件中找到对应的SQL

通过类函数的参数statementName与配置文件中statement配置的id相匹配

 

2.     bean中的数据如何映射给SQL文中对应的输入参数

a.     通过参数变量名称与bean中对应属性名称相匹配

<statement id=”statementName” parameterClass=” examples.domain.Product”>

insert into PRODUCT values (#id#, #description#, #price#)

</statement>

 

b.     通过参数变量的出现顺序相 匹配

<parameterMap id=”insert-product-param” class=”com.domain.Product”>

<parameter property=”id”/>

<parameter property=”description”/>

</parameterMap>

<statement id=”insertProduct” parameterMap=”insert-product-param”>

insert into PRODUCT (PRD_ID, PRD_DESCRIPTION) values (?,?);

</statement>

 

3.     map中的数据如何映射给SQL文中对应的输入参数

a.     通过参数变量名称与map中对应key相匹配

<statement id=”statementName” parameterClass=” java.util.Map”>

insert into PRODUCT values (#id#, #description#, #price#)

</statement>

 

HashMap hm = new HashMap();

hm.put(“id”,”value”);

hm.put(“description”,”value”);

hm.put(“price”,”value”);

sqlMapClient.queryForList(“statementName”, hm,…………);

 

 

 

4.     基本数据类型的数据如何映 射给SQL文中对应的输入参数

基本数据类型与参数11,没啥匹配的问题。不过官 方的开发指南中强调参数要写成#value#这种写法,原因不明。

<statement id=”insertProduct” parameter=”java.lang.Integer”>

select * from PRODUCT where PRD_ID = #value#

</statement>

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

七,       关于映射时返回值的匹配问题

1.     查询结果如何映射给bean中的对应属性

a.     通过查询结果的字段名称与bean中对应属性名称相匹配

<statement id=”getProduct” resultClass=”com.ibatis.example.Product”>

select

PRD_ID as id,

PRD_DESCRIPTION as description

from PRODUCT

where PRD_ID = #value#

</statement>

 

官 方的开发指南中说这种写法叫做隐式ResultMap

 

b.     指定查询结果的字段名称与bean中对应属性名称的映射关系

<resultMap id=”get-product-result” class=”com.ibatis.example.Product”>

<result property=”id” column=”PRD_ID”/>

<result property=”description” column=”PRD_DESCRIPTION”/>

<result property=”subCode” column=”PRD_SUB_CODE” nullValue=”-999”/>

</resultMap>

 

以上,数据类型通过反射与对 应的属性类型自动匹配,极少数时候可能需要通过resultMapjavaType属性进行设定,参考后面关于Result Map外部形式中各个参数的说明

 

2.     查询结果如何设定给Map

a.     通过查询结果的字段名称与map中对应key相匹配

<resultMap id=”get-product-result” class=”java.util.HashMap”>

<result property=”id” column=”PRD_ID”/>

<result property=”code” column=”PRD_CODE”/>

<result property=”description” column=”PRD_DESCRIPTION”/>

<result property=”suggestedPrice” column=”PRD_SUGGESTED_PRICE”/>

</resultMap>

 

<statement id=”getProductCount” resultClass=”java.util.HashMap”>

select * from PRODUCT

</statement>

 

b.     指定查询结果的字段名称与bean中对应属性名称的映射关系

bean基本相同,参考使用bean作为返回结果的写法

 

3.     查询结果如何映射给基本数 据类型

只能指定一个返回值,名字可 以随便,一般采用value,val

<resultMap id=”get-product-result” class=”java.lang.String”>

<result property=”value” column=”PRD_DESCRIPTION”/>

</resultMap>

 

或 者

<statement id=”getProductCount” resultClass=”java.lang.Integer”>

select count(1) as value

from PRODUCT

</statement>

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

八,       关于Parameter Map外部形式中各个参数的说明

<parameterMap id=”parameterMapName” [class=”com.domain.Product”]>

<parameter

property =”propertyName”

[jdbcType=”VARCHAR”]

[javaType=”string”]

[nullValue=”NUMERIC”]

[null=”-9999999”]/>

<parameter …… />

<parameter …… />

</parameterMap>

1.JdbcType

属 性jdbcType用于显式地指定给本属性(property) 赋值的数据库字段的数据类型。对于某些特定的操作,如果不指定字段的数据类型,某些JDBC Driver无 法识别字段的数据类型。

 

正 常情况下,只有当字段可以为NULL时才需要jdbcType属 性。另一需要指定jdbcType属性的情况是字段类型为日期时间类型的情况。因为Java只 有一个Date类型(java.util.Date), 而大多数SQL数据库有多个-通常至少有3种。因此,需要指定字段类型是DATE还是DATETIME。

 

注意!当使用Oracle Driver时,如果没有给可以为NULL的字段指定jdbcType属性,当试图给这些字段赋 值NULL时,会出现“Invalid column type”错误。

 

2.javaType

属 性javaType用于显式地指定被赋值参数Java属 性的类名。正常情况下,这可以通过反射从Java Bean的 属性获得

 

3.nullValue, null

   用 于指定NULL的替换值。就是说,当Java Bean的属性值等于指定值时,相应的字段将赋值NULL。 这个特性允许在应用中给不支持null的数据类型(即intdoublefloat等) 赋值null。当这些数据类型的属性值匹配null值 (即匹配-9999)时,NULL将 代替null值写入数据库。

      一个完整的例子

<parameterMap id=”insert-product-param” class=”com.domain.Product”>

<parameter

property=”id”

jdbcType=”NUMERIC”

javaType=”int”

nullValue=”-9999999”/>

<parameter

property=”description”

jdbcType=”VARCHAR”

nullValue=”NO_ENTRY”/>

</parameterMap>

 

<statement id=”insertProduct” parameterMap=”insert-product-param”>

insert into PRODUCT (PRD_ID, PRD_DESCRIPTION) values (?,?);

</statement>

 

      简化写法

<statement id=”insertProduct” parameterClass=”com.domain.Product”>

insert into PRODUCT (PRD_ID, PRD_DESCRIPTION)

values (#id:NUMERIC#, #description:VARCHAR#);

</statement>

 

或者:

 

<statement id=”insertProduct” parameterClass=”com.domain.Product”>

insert into PRODUCT (PRD_ID, PRD_DESCRIPTION)

values (#id:NUMERIC:-999999#, #description:VARCHAR:NO_ENTRY#);

</statement>

 

 

 

 

九,       Result Map外部形式中各个参数的说明

<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>

1. columnIndex

属性columnIndex是可选的,用于改善性能。 属性columnIndex的值是ResultSet中用于赋值Java Bean属性的字段次序号。在99%的应用中,不太可能需要牺牲可读性来换取性能。使用columnIndex,某些JDBC Driver可以大幅提高性能,某些则没有任何效果。

 

2.javaType

属性javaType用于显式地指定被赋值的Java Bean属性的类型。正常情况下,这可以通过反射从Java Bean的属性获得,但对于某些映射 (例如MapXML document),框架不能通过这种方法来 获知。如果没有设置javaType, 同时框架也不能获知类型信息,类型将被假定为Object

 

3.jdbcType,nullValue, null

   Parameter Map

4.select

属 性select用于描述对象之间的关系,并自动地装入复杂类型(即用户定义的类型)属性的数 据。属性select的值必须是另外一个mapped statement元素的名称。在同一个result元 素中定义的数据库字段(column属性)以及property属 性,将被传给相关的mapped statement作为参数。因此,字段的数据类型必须是SQL Map支持的简单数据类型。关于简单数据类型和复杂类型之间映射/关 系的信息,参照后面章节更详细的讨论。

 

具 体参考稍后关于复杂类型属性的例子

十,       复杂类型属性说明

1.关于复杂类型属性的例子

<resultMap id=”get-product-result” class=”com.ibatis.example.Product”>

<result property=”id” column=”PRD_ID”/>

<result property=”description” column=”PRD_DESCRIPTION”/>

<result property=”category” column=”PRD_CAT_IDselect=”getCategory”/>

</resultMap>

<resultMap id=”get-category-result” class=”com.ibatis.example.Category”>

<result property=”id” column=”CAT_ID”/>

<result property=”description” column=”CAT_DESCRIPTION”/>

</resultMap>

<statement id=”getProduct” parameterClass=”int” resultMap=”get-product-result”>

select * from PRODUCT where PRD_ID = #value#

</statement>

<statement id=”getCategory” parameterClass=”int” resultMap=”get-category-result”>

select * from CATEGORY where CAT_ID = #value#

</statement>

 

         避 免N1 Select1:1  

<resultMap id=”get-product-result” class=”com.ibatis.example.Product”>

<result property=”id” column=”PRD_ID”/>

<result property=”description” column=”PRD_DESCRIPTION”/>

<result property=”category.id” column=”CAT_ID” />

<result property=”category.description” column=”CAT_DESCRIPTION” />

</resultMap>

<statement id=”getProduct” parameterClass=”int” resultMap=”get-product-result”>

select *

from PRODUCT, CATEGORY

where PRD_CAT_ID=CAT_ID

and PRD_ID = #value#

</statement>

 

 

2.关于复杂类型级和属性的例子

<resultMap id=”get-category-result” class=”com.ibatis.example.Category”>

<result property=”id” column=”CAT_ID”/>

<result property=”description” column=”CAT_DESCRIPTION”/>

<result property=”productList” column=”CAT_ID” select=” getProductsByCatId”/>

</resultMap>

<resultMap id=”get-product-result” class=”com.ibatis.example.Product”>

<result property=”id” column=”PRD_ID”/>

<result property=”description” column=”PRD_DESCRIPTION”/>

</resultMap>

<statement id=”getCategory” parameterClass=”int” resultMap=”get-category-result”>

select * from CATEGORY where CAT_ID = #value#

</statement>

<statement id=”getProductsByCatId” parameterClass=”int” resultMap=”get-product-result”>

select * from PRODUCT where PRD_CAT_ID = #value#

</statement>

 

         避 免N1 Select1:1  

暂 时无解,在新版本中可能会对应

 

3.组合键值或多个复杂参数属性

<resultMap id=”get-order-result” class=”com.ibatis.example.Order”>

<result property=”id” column=”ORD_ID”/>

<result property=”customerId” column=”ORD_CST_ID”/>

<result property=”payments” column=”{itemId=ORD_ID, custId=ORD_CST_ID}

select=” getOrderPayments”/>

</resultMap>

<statement id=”getOrderPayments” resultMap=”get-payment-result”>

select * from PAYMENT

where PAY_ORD_ID = #itemId#

and PAY_CST_ID = #custId#

</statement>

十一,   在查询statement中指定cacheModel属性

<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>

 

<statement id=”getProductList” cacheModel=”product-cache”>

select * from PRODUCT where PRD_CAT_ID = #value#

</statement>

 

1Serializable可读写缓存

正 如您所知道的,只对当前Session有效的缓存对整体应用性能的提高作用有限。Serializable可读写缓存可以提高整体应用(而不仅仅是每个Session)的性能。这种缓存为每一个Session返回缓存对象不同的实例(复本)。因此每一个Session都可以安全修改返回的对象。不同之处在于,通常您希望从缓存中得到同一个对象,但这种情况下得到的是不同的对象。还有,每一个 缓冲在Serializable缓 存的对象都必须是Serializable的。 这意味着不能同时使用Serializable缓存和延迟加载,因为延迟加载代理不是Serializable的。想知道如何把Serializable缓存,延迟加载和联合查询结合起来使用,最好的方法是尝试。要使用Serializable缓 存,设置readOnly=falseserialize=true。缺省情况下,缓存是只读模式,不使用Serializable缓存。只读缓存不需要Serializable

 

 

 

 

 

 

 

 

 

2Type

    a.type=MEMORY

MEMORY cache实现只认识一个<property>元素。这个名为reference-type属性的值必须是STRONGSOFTWEAK三者其一。这三个值分别对应于JVM不同的内存reference类型。

<property name=”reference-type” value=”WEAK” />

 

 

    b.type=LRU

LRU Cache实现用近期最少使用原则来确定如何从Cache中清除对象。

       <property name=”cache-size” value=”1000” />

 

    c.type=FIFO

       FIFO Cache实 现用先进先出原则来确定如何从Cache中清除对象。

<property name=”size” value=”1000” />

 

d.type= OSCACHE  没 用过,没研究过。这个不太懂,哈

OSCACHE Cache实现是OSCache2.0缓存引擎的一个Plugin。它具有高度的可配置性,分布式,高度的灵活性。

 

OSCACHE实现不使用property元素,而是在类路径的根路径中使用标准的oscache.properties文件进行配置。在oscache.properties文件中,您可以配置Cache的算法(和上面讨论的算法很类似),Cache的大小,持久化方法(内存,文件等)和集群方法。

要获得更详细的信息,请参考OSCache文档。OSCache及其文档可以从OpenSymphony网站上获取:

http://www.opensymphony.com/oscache/

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

十二,   动态Mapped Statement

<select id="dynamicGetAccountList"

cacheModel="account-cache"

resultMap="account-result"

>

select * from ACCOUNT

<isGreaterThan prepend="and" property="id" compareValue="0">

where ACC_ID = #id#

</isGreaterThan>

order by ACC_LAST_NAME

</select>

上 面的例子中,根据参数beanid属性的不同情况,可创建两个可能的语句。如果参数id大于0,将创建下面的语句:

select * from ACCOUNT where ACC_ID = ?

或 者,如果id参数小于等于0,将创建下面的语句:

select * from ACCOUNT

 

1.二元条件元素

二 元条件元素将一个属性值和一个静态值或另一个属性值比较,如果条件为,元素体的内容将被包括在查询SQL语句中。

 

二元条件元素的属性:

prepend - 可被覆盖的SQL语句组成部分,添加在语句的前面(可选)

property - 被比较的属性(必选)

compareProperty - 另一个用于和前者比较的属性(必选或选择compareValue

compareValue - 用于比较的值(必选或选择compareProperty

<isEqual>

比较属性值和静态值或另一个属性值是否相等。

<isNotEqual>

比较属性值和静态值或另一个属性值是否不相等。

<isGreaterThan>

比较属性值是否大于静态值或另一个属性值。

<isGreaterEqual>

比较属性值是否大于等于静态值或另一个属性值。

<isLessThan>

比较属性值是否小于静态值或另一个属性值。

<isLessEqual>

比较属性值是否小于等于静态值或另一个属性值。

例子:

<isLessEqual prepend=”AND” property=”age” compareValue=”18”>

ADOLESCENT = ‘TRUE’

</isLessEqual>

 

2.一元条件元素

一 元条件元素检查属性的状态是否符合特定的条件。

一元条件元素的属性:

prepend - 可被覆盖的SQL语句组成部分,添加在语句 的前面(可选)

property - 被比较的属性(必选)

<isPropertyAvailable>

检查是否存在该属性(存在parameter bean的属性)。

<isNotPropertyAvailable>

检查是否不存在该属性(不存在parameter bean的属性)。

<isNull>

检查属性是否为null

<isNotNull>

检查属性是否不为null

<isEmpty>

检查Collection.size()的值,属性的StringString.valueOf(),是否为null或空(“”size() < 1)。

<isNotEmpty>

检查Collection.size()的值,属性的StringString.valueOf(),是否不为null或 不为空(“”size() > 0)。

例子:

<isNotEmpty prepend=”AND” property=”firstName” >

FIRST_NAME=#firstName#

</isNotEmpty>

 

3其他元素

Parameter Present:这些元素检查参数对象 是否存在。

Parameter Present的属性:

prepend - 可被覆盖的SQL语句组成部分,添加在语 句的前面(可选)

<isParameterPresent>

检 查是否存在参数对象(不为null)。

<isNotParameterPresent>

检 查是否不存在参数对象(参数对象为null)。

例子:

<isNotParameterPresent prepend=”AND”>

EMPLOYEE_TYPE = ‘DEFAULT’

</isNotParameterPresent>

 

4Iterate:这属性遍历整个集合,并为List集 合中的元素重复元素体的内容。

Iterate的属性:

prepend - 可被覆盖的SQL语句组成部分,添加在语句的前面(可选)

property - 类型为java.util.List的用于遍历的元素(必选)

open - 整个遍历内容体开始的字符串,用于定义括号(可选)

close -整个遍历内容体结束的字符串,用于定义括号(可选)

conjunction - 每次遍历内容之间的字符串,用于定义ANDOR(可选)

<iterate>

遍历类型为java.util.List的元素。

例子:

<iterate prepend=”AND” property=”userNameList”

open=”(” close=”)” conjunction=”OR”>

username=#userNameList[]#

</iterate>

注意:使用<iterate>时,在List元素名后面包括方括号[]非常重要,方括号[]将对象标记为List,以防解析器简单地将List输出成String

 

一,       注 意事项

1.关于特殊字符

因为SQL语句是嵌在XML文档中的, 因此有些特殊的字符不能直接使用,例如大于号和小于号(<>)。幸运的 是,解决的办法很简单,只需将包含特殊字符的SQL语句放在XMLCDATA区里面就可 以了。例 如:


<statement id="getPersonsByAge" parameterClass=”int” resultClass="examples.domain.Person">

<![CDATA[

SELECT *

FROM PERSON

WHERE AGE > #value#

]]>

</statement>

 

 

 

2.关于多个SqlMap.xml 中id冲突问题

问题描述:

sql-map-config中引用多个sqlmap.xml,多个sqlmap.xml中存在相同的statementname的时候,ibatis如何判断当前我准备使用哪 一个sqlmap.xml中的statementname对应的sql语句

      

       解决方法:

SqlMapConfig.xml中的settings标签中存在一个属性useStatementNamespaces当这个设定 为true的时候,那 么iBatis通过SqlMap.xmlnamespace.id来查找对应 的sqlid,从而避免 这个问题。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

二,       其他

1.自动生成的主健

<insert id="insertProduct-ORACLE" parameterClass="com.domain.Product">

<selectKey resultClass="int" keyProperty="id" >

SELECT STOCKIDSEQUENCE.NEXTVAL AS ID FROM DUAL

</selectKey>

insert into PRODUCT (PRD_ID,PRD_DESCRIPTION)

values (#id#,#description#)

</insert>

 

<!— Microsoft SQL Server IDENTITY Column Example -->

<insert id="insertProduct-MS-SQL" parameterClass="com.domain.Product">

insert into PRODUCT (PRD_DESCRIPTION)

values (#description#)

<selectKey resultClass="int" keyProperty="id" >

SELECT @@IDENTITY AS ID

</selectKey>

</insert>

 

2.调用存储过程

<parameterMap id="swapParameters" class="map" >

<parameter property="email1" jdbcType="VARCHAR" javaType="java.lang.String" mode="INOUT"/>

<parameter property="email2" jdbcType="VARCHAR" javaType="java.lang.String" mode="INOUT"/>

</parameterMap>

<procedure id="swapEmailAddresses" parameterMap="swapParameters" >

{call swap_email_address (?, ?)}

</procedure> SELECT @@IDENTITY AS ID

 

十五,   Sample

1.java类,生成iBatis数据库操作对象

public class MyAppSqlConfig {

private static final SqlMapClient sqlMap;

static {

try {

String resource = “com/ibatis/example/sql-map-config.xml”;

Reader reader = Resources.getResourceAsReader (resource);

sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);

} catch (Exception e) {

e.printStackTrace();

throw new RuntimeException (“”);

}

}

public static getSqlMapInstance () {

return sqlMap;

}

}

 

2.配置文件:

Continue reading 【转】笑着学习笔记iBatis入门

【转】Instruction about how to load “.csv” file into MySQL

1.       Change the configuration file of MySQL. (MySQL can’t identify some incorrect strings of the .csv file we want to load, so that we have to change the setting of MySQL)


l         Open your "my.ini" file within the MySQL installation directory, and look for the text "sql-mode". Find:


l         Add the following code to “my.ini” file



2.       Download the .csv files and unzip it:


File NameDownload Link
1. GeoIPCountryCSV.zip (It contains one database file)http://www.maxmind.com/app/geoip_country
2. GeoLiteCity_20100601.zip (It contains two database files)http://www.maxmind.com/app/geolitecity



Note: Actually, there is one database named GeoLiteRegion, which doesn’t have free version right now. So we didn’t choose to use it.




3.       Use MySQL Workbench to load the unzipped .csv files to database


l         According to the number of columns of the .csv file, we need to create the corresponding table and give a name to each column.

l         After the table has been established, we can use the following command to automatically load the data :


If you guys are still confusing about the code above, you check the following websites out:

http://forums.mysql.com/read.php?79,219901,219901
http://www.tech-recipes.com/rx/2345/import_csv_file_directly_into_mysql/

建议使用dat文件读取。

Continue reading 【转】Instruction about how to load “.csv” file into MySQL

extjs grid使用总结

版本:3.2.1,主要使用在BannerAdmin上:

1:使用store要注意:
一般使用record.beginEdit, set,endEdit,---(update event)-->commit/reject的步骤来更新/还原数据,直接修改record的data的值不会触发update等事件,估计这样的话reject也不会起作用。
2:EditGrid的默认selmode是CellSelectModel.CheckColumn是在ux包里面的。发现直接修改CheckColumn绑定的record.data后,会反映在CheckColumn上。
3:EditGrid要支持拖拽的话,还要改代码:[见cm.js]
Ext.override(Ext.grid.GridPanel, {
               getDragDropText : function() {
                   var sm = this.selModel;

                   var count;
                   if (sm instanceof Ext.grid.CellSelectionModel) {
                       count = 1;
                   } else {
                       count = sm.getCount();
                   }
                   return String.format(this.ddText, count, count == 1
                                   ? ''
                                   : 's');
               }
           });
   Ext.override(Ext.grid.GridDragZone, {
               getDragData : function(e) {
                   var t = Ext.lib.Event.getTarget(e);
                   var rowIndex = this.view.findRowIndex(t);
                   var cellIndex = this.view.findCellIndex(t);

                   if (rowIndex !== false) {
                       var sm = this.grid.selModel;

                       // RowSelectionModel
                       if (sm instanceof Ext.grid.RowSelectionModel) {
                           if (!sm.isSelected(rowIndex) || e.hasModifier()) {
                               sm.handleMouseDown(this.grid, rowIndex, e);
                           }
                           return {
                               grid : this.grid,
                               ddel : this.ddel,
                               rowIndex : rowIndex,
                               selections : sm.getSelections()
                           };
                       }

                       // CellSelectionModel
                       if (sm instanceof Ext.grid.CellSelectionModel) {
                           sel = sm.getSelectedCell();

                           rowAlreadySelected = sel && sel[0] == rowIndex;

                           if (!rowAlreadySelected || e.hasModifier()) {
                               sm.handleMouseDown(this.grid, rowIndex,
                                       cellIndex, e);
                           }

                           store = this.grid.getStore();
                           sel = sm.getSelectedCell();
                           if (sel)
                               return {
                                   grid : this.grid,
                                   ddel : this.ddel,
                                   rowIndex : rowIndex,
                                   selections : [store.getAt(sel[0])]
                               };
                           else
                               return {
                                   grid : this.grid,
                                   ddel : this.ddel,
                                   rowIndex : rowIndex,
                                   selections : []
                               };
                       }
                   }
                   return false;

               }
           });

Continue reading extjs grid使用总结

gzip系列

ie5就开始支持gzip了[待考证,反正ie6是支持的]

传统的JS压缩(删除注释,删除多余空格等)提供的压缩率有时还是不尽不意, 幸亏现在的浏览器都支持压缩传输(通过设置http header的Content-Encoding=gzip),可以通过服务器的配置(如apache)为你的js提供压缩传输,或是appfuse中使 用的GZipFilter使tomcat也提供这种能力

现在的问题是这种动态的压缩会导致服务器CPU占用率过高,现在我想到的解决辨法是通过提供静态压缩(就是将js预先通过gzip.exe压缩 好)

一.下面描述在tomcat中的应用
httpServletResponse.setHeader("Content-Encoding", "gzip");//主要是这一句,但是如果仅仅加个header,让容器自己输出的话,没有起作用,返回流的头部还是没有gzip信息,所以还得自己负责返回文件流,这个又加重了服务端cpu,但是减少了带宽。
对于chrome,还要返回Content-Type,否则会被忽略
httpServletResponse.setHeader("Content-Type", "text/plain");//这只对于非图片类型

对于safari,直接.gz为扩展名的它处理有问题,要改成别的如.jgz

1.将prototype.js通过gzip.exe压缩保存成prototype.gzjs
2.设置header,我编写了一个简单的AddHeadersFilter来将所有以gzjs结尾的文件增加设置header Content-Encoding=gzip
web.xml中的配置

Java 代码
  1. <filter> 
  2.     <filter-name>AddHeaderFilter</filter-name> 
  3.     <filter-class
  4.         badqiu.web.filter.AddHeaderFilter 
  5.     </filter-class
  6.     <init-param> 
  7.         <param-name>headers</param-name> 
  8.         <param-value>Content-Encoding=gzip</param-value> 
  9.     </init-param> 
  10. </filter> 
  11.  
  12. <filter-mapping> 
  13.     <filter-name>AddHeaderFilter</filter-name> 
  14.     <url-pattern>*.gzjs</url-pattern> 
  15. </filter-mapping> 

测试prototype.js是否正常的代码

Java 代码
  1. <html> 
  2. <head> 
  3. <!-- type="text/javascript"不可少,有些浏览器缺少这个不能运行,具体已经忘记 了 --> 
  4. <script src="prototype.gzjs" type="text/javascript"></script> 
  5. </head> 
  6. <body> 
  7.     <input id="username" name="username" value="badqiu"/><br /> 
  8.     <input id="email" value="[email protected]"/> 
  9. <script> 
  10.     <!-- 测 试prototype的方法是否正常--> 
  11.     alert($F('username')) 
  12. </script> 
  13. </body> 
  14. </html> 

在Apache httpd中可以直接通过在httpd.conf增加AddEncoding x-gzip .gzjs来映射.gzjs文件的header

二.相关压缩率数据
1. prototype.js 1.5.0_rc0原始大小56KB,未经任何处理直接使用gzip压缩为12KB,总压缩率79%
2. 通过js压缩工具压缩过的protytype.js为20KB,使用gzip压缩为10KB,总压缩率为83%
3. 实际项目中的多个js合并成的文件 439KB,直接通过gzip压缩为85KB,总压缩率81%
4. 439KB经过js压缩为165KB,再经过gzip压缩为65KB,总压缩率86%

基本上你都可以忽略js压缩工具的压缩率,直接使用gzip压缩

gzip下载地址 http://www.gzip.org
tomcat的压缩配置示例下载地址: http://www.blogjava.net/Files/badqiu/gziptest.rar

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

Wordpress之终极Gzip兼容IE6

为了这Gzip我可没有少费功夫啊,之前我已经写过三篇文章《开启GZIP,提速 Wordpress》《给Wordpress开启Gzip 功能》《完美启用Gzip压缩JS、 CSS》,三篇文章三个方法,各有特色,一直以来我是将这三个Gzip结合使用的,但是始终没有达到我期望的最佳效果,因为启用后就不得不放弃 IE6的用户。这一bug让我在使用Gzip时很尴尬,之后我也试过给浏览器设置白名单,希望IE6跳过Gzip,最后以失败告终。不过今天终于让我找到 一个可以兼顾IE6的开启Gzip的方法,让我的Wordpress载入速度又上了一个台阶。特地将此方法转载来和大家分享,因为原文是繁体,我就简化了 一下:

1、下载gzip.zip, 解压后上传至网站根目录。

2、修改根目录的.htaccess,增加gz的识别支援及网址改写:

#識辨gz檔案的支援
<Files *.js.gz>
  AddEncoding gzip .js
  ForceType application/x-javascript
</Files>
<Files *.css.gz>
  AddEncoding gzip .css
  ForceType text/css
</Files>

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /

#wordpress靜態 網址,如果沒有使用,就略過
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

#讀到css和js檔,就 重導至gzip.php
RewriteRule (.*.css$|.*.js$) gzip.php?$1 [L]

#讀到.css,判斷如果 瀏覽器支援gzip且.css.gz檔存在,就進行重導
RewriteCond %{HTTP:Accept-encoding} gzip
RewriteCond %{REQUEST_FILENAME}.gz -f
RewriteRule ^(.*).css $1.css.gz [L,QSA]

#讀到.js,判斷如果瀏 覽器支援gzip且.js.gz檔存在,就進行重導
RewriteCond %{HTTP:Accept-encoding} gzip
RewriteCond %{REQUEST_FILENAME}.gz -f
RewriteRule ^(.*).js $1.js.gz [L,QSA]
</IfModule>

3、浏览自己的网站,让CSS和JS产生gz档,并将相应的.gz文件权限设置为777。

4、最后,再次改写.htaccess,把以下代码注释掉或删除。

RewriteRule (.*.css$|.*.js$) gzip.php?$1 [L]

完毕。此Gzip方法是至今我最满意的,效果最显著的,强烈推荐。不过在修改CSS和JS后,还要还原那句代码并重做第3、4步。所以该方法稍 有些复杂,比较适合像我一样喜欢折腾Wordpress的童鞋们。

给 Wordpress 开启 Gzip 功能

曾经我为了给 Wordpress 开启 Gzip 功能真是煞费苦心,但最终还是成功了,并写下日志《开启GZIP,提速 Wordpress》分享给大家。据willin的反馈,他使用该方法感觉 不错,但是我自己用这个方法却发现主题在IE6下裸奔了,至今没有找到问题的根源,之后只好弃用了该方法。郁闷~

但是我一直没有放弃对开启 Gzip 的追求,皇天不负有心人,终于让我找到了两个给 Wordpress 开启 Gzip 的方法,且比在《开启GZIP,提速 Wordpress》中提到的方法更简单,更实用,也没有在 IE6 下裸奔的现象,值得推荐。至于什么是 Gzip、如何检测网站是否开启 Gzip 功能等问题本文就不多作熬述了,欲知答案请移步《开启GZIP,提速 Wordpress》。下面马上切入正题:

方法一:

gzippy 插件。

这对于懒人或者菜菜们来说是个福音和首选,这个插件解压后也不足2K,可谓短小精悍,且上传安装之后也无需另外设置,很方便实用。

下载地址:http://wordpress.org/extend/plugins/gzippy/

方法二:

定义 php.ini。

新建一个名为 php.ini 的文件,输入以下内容,保存并上传至网站根目录即可。

output_buffering = Off
output_handler =
zlib.output_compression = On

因为本人对插件有抵触情绪,能 用代码搞定的就绝不用插件解决!所以我现在用的是方法二,压缩率达到73%,还是比较让人满意的。现在我的 YSlow 成绩又回到了 Grade B,真要感谢 Gzip 的压缩功能啊.


完美启用Gzip压缩JS、CSS

这已经是我自《开启GZIP,提速 Wordpress》《给Wordpress开启Gzip 功能》两篇文章后第三次介绍Wordpress中的Gzip功能,而这三篇中所涉及的Gzip又各有不同,可以结合实用。在《给Wordpress开启Gzip 功能》中提到的Gzip功能很简单,但是只对Wordpress输出的html进行压缩,所以效果有限。而这篇文章提及的Gzip功能将对 Wordpress中的重头戏JS和CSS进行压缩,这将使Wordpress的载入速度达到一个质的飞跃!

1、把模板目录下的style.css复制一份出来,命名为style.css.php,接着在style.css.php顶部加入这句:

<?php if(extension_loaded('zlib')) {ob_start('ob_gzhandler');} header("Content-type: text/css"); ?>

在最后加上下面代码:

<?php if(extension_loaded('zlib')) {ob_end_flush();} ?>

2、按照下面的方式修改header.php中的css连接

原来的:

<link rel="stylesheet" type="text/css" media="screen" href="/style.css"/>

修改后的:

<link rel="stylesheet" type="text/css" media="screen" href="/style.css.php"/>

这样,你的CSS就被Gzip压缩了,同样的方法可以压缩你的JS。只是在JS的顶部加入的是如下代码:

<?php if ( extension_loaded('zlib') ) {ob_start('ob_gzhandler');} header("Content-Type: text/javascript"); ?>

说说我自己使用Gzip压缩后的效果吧,在《开启GZIP,提速 Wordpress》中我就提到,根据YSlow的要求,其中Compress components with gzip这项,我的得分仅为F,严重地影响了小站的整体评级。开启Gzip之后,我再用YSlow去检测,现在我的得分是Grade A!再贴个图让各位有个直观的理解,看看我的JS和CSS减了多少肥吧。JS和CSS的大小从102.1K直降到33.8K,足足减少了三分之二的文件大 小,如果你有用prototype.js这样的大型JS,那压缩之后的效果就更可观了。!

开启此Gzip功能比《给Wordpress开启Gzip 功能》中提到的Gzip要复杂的多,因为要对所有JS和CSS一一修改,且要找到并修改调用该JS和CSS的代码,如果你还是刚刚踏入 Wordpress大家庭的小菜菜,那我还是建议你用《给Wordpress开启Gzip 功能》中的插件或php.ini来实现Gzip。

最后友情提醒一下,因为使用此Gzip,需要修改比较多的文件和代码,所以记得备份哟,如果做错也好有个挽回的余地。

开启GZIP,提速Wordpress

今天我用FireFox的YSlow组件对小站进行了评测,结果仅为Grade C,实在是差强人意。虽然自认为本站的速度已经算是很不错了,话说自从换了小张童鞋的息壤主 机后,小站的速度也是突飞猛进,但是为了满足小小的虚容心和完美主义性格,Grade C的结果在我看来是不合格的,我的目标是Grade A!我需要优化、优化、再优化,提速、提速、再提速!

根据YSlow的要求,其中Compress components with gzip这项,我的得分仅为F,严重地影响了小站的整体评级。本文也就重点谈谈如何开启GZIP压缩网页从而给Wordpress提速。

三言两语先简单介绍下GZIP功能,我G来的。GZIP功能可以大幅度地压缩CSS、JS之类的文本型文件,压缩率达60%-90%,挺可观 的。GZIP压缩功能在Wordpress2.3-2.5版本里都是自带的,之后就没有了,我现在用的是Wordpress2.7.1,就更没有这个功能 了。那如何手动开启Wordpress2.7+的GZIP功能呢?

在开始之前,我们先做点准备工作,你也可以用YSlow查一下你的网站评级,然后登陆http://www.whatsmyip.org/mod_gzip_test/检测一下你的网站是否已经开 启了GZIP,等事后可以作个比较。下面是我开启GZIP之前的测试截图。

wange.im

废话到此为止,进入正题。

1.开启GZIP功能。在根目录下的index.php找到

define(’WP_USE_THEMES’, true);

在其后插入如下代码:

if(ereg(’gzip’,$_SERVER['HTTP_ACCEPT_ENCODING'])){//判断浏览器是否支持Gizp
if(substr($_SERVER['REQUEST_URI'],0,10)!=’/download /’)//排除不需要Gzip压缩的目录
ob_start(’ob_gzhandler’);//打开Gzip压缩
}

2.在.htaccess里面加上RewriteRule (.*.css$|.*.js$) gzip.php?$1 [L]

如果你那可怜的主机不支持.htaccess可写,很遗憾,你就不用往下看了。

3.压缩CSS和JS文件。你可以复制以下代码保存为gzip.php,或者点此下载我的gzip.php文件,下载解压之后上传至根目录即可。让所有的CSS和JS文件访问就以相对根目 录的路径以GET变量传递到了gzip.php,交给gzip.php来全权处理了。

<?php
define('ABSPATH', dirname(__FILE__).'/');

$cache = true;//Gzip压缩开关
$cachedir = 'wp-cache/';//存放gz文件的目录,确保可写

$gzip = strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip');
$deflate = strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'deflate');
$encoding = $gzip ? 'gzip' : ($deflate ? 'deflate' : 'none');

if(!isset($_SERVER['QUERY_STRING'])) exit();

$key=array_shift(explode('?', $_SERVER['QUERY_STRING']));
$key=str_replace('../','',$key);

$filename=ABSPATH.$key;

$symbol='^';

$rel_path=str_replace(ABSPATH,'',dirname($filename));
$namespace=str_replace('/',$symbol,$rel_path);

$cache_filename=ABSPATH.$cachedir.$namespace.$symbol.basename($filename).'.gz';//生成gz文件路径

$type="Content-type: text/html"; //默认的类型信息

$ext = array_pop(explode('.', $filename));//根据后缀判断文件类型信息
switch ($ext){
  case 'css':
   $type="Content-type: text/css";
   break;
  case 'js':
   $type="Content-type: text/javascript";
   break;
  default:
   exit();
}

if($cache){
if(file_exists($cache_filename)){//假如存在gz文件

  $mtime = filemtime($cache_filename);
  $gmt_mtime = gmdate('D, d M Y H:i:s', $mtime) . ' GMT';

  if( (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) &&
        array_shift(explode(';', $_SERVER['HTTP_IF_MODIFIED_SINCE'])) ==  $gmt_mtime)
   ){

   // 浏览器cache中的文件修改日期是否一致,将返回304
   header ("HTTP/1.1 304 Not Modified");
   header("Expires: ");
   header("Cache-Control: ");
   header("Pragma: ");
   header($type);
   header("Tips: Cache Not Modified (Gzip)");
   header ('Content-Length: 0');

  }else{

   //读取gz文件输 出
   $content = file_get_contents($cache_filename);
   header("Last-Modified:" . $gmt_mtime);
   header("Expires: ");
   header("Cache-Control: ");
   header("Pragma: ");
   header($type);
   header("Tips: Normal Respond (Gzip)");
   header("Content-Encoding: gzip");
   echo $content;
  }

}else if(file_exists($filename)){ //没有对应的gz文件

  $mtime = mktime();
  $gmt_mtime = gmdate('D, d M Y H:i:s', $mtime) . ' GMT';

  $content = file_get_contents($filename);//读取文件
  $content = gzencode($content, 9, $gzip ? FORCE_GZIP : FORCE_DEFLATE);//压缩文件内容

  header("Last-Modified:" . $gmt_mtime);
  header("Expires: ");
  header("Cache-Control: ");
  header("Pragma: ");
  header($type);
  header("Tips: Build Gzip File (Gzip)");
  header ("Content-Encoding: " . $encoding);
        header ('Content-Length: ' . strlen($content));
  echo $content;

  if ($fp = fopen($cache_filename, 'w')) {//写入gz文件,供下次使用
                fwrite($fp, $content);
                fclose($fp);
            }

}else{
  header("HTTP/1.0 404 Not Found");
}
}else{ //处理不使用Gzip模式下 的输出。原理基本同上
if(file_exists($filename)){
  $mtime = filemtime($filename);
  $gmt_mtime = gmdate('D, d M Y H:i:s', $mtime) . ' GMT';

  if( (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) &&
  array_shift(explode(';', $_SERVER['HTTP_IF_MODIFIED_SINCE'])) ==  $gmt_mtime)
  ){

  header ("HTTP/1.1 304 Not Modified");
  header("Expires: ");
  header("Cache-Control: ");
  header("Pragma: ");
  header($type);
  header("Tips: Cache Not Modified");
  header ('Content-Length: 0');

}else{

  header("Last-Modified:" . $gmt_mtime);
  header("Expires: ");
  header("Cache-Control: ");
  header("Pragma: ");
  header($type);
  header("Tips: Normal Respond");
  $content = readfile($filename);
  echo $content;

  }
}else{
  header("HTTP/1.0 404 Not Found");
}
}

?>

  搞定,再去http://www.whatsmyip.org/mod_gzip_test/检 测一下你的网站是否已经开启了GZIP,如果上述步骤都操作正确,那测试结果应该如下图所示。

wange.im

既然已经对CSS和JS文件压缩了,那我们再用YSlow来评测一下等级。Oh耶!我的小站从Grade C上升到Grade B了,不过说实话,虽然把CSS和JS文件压缩了72%,但并没有很明显地提速,因为本来就已经够快的了,哈哈。

说些题外话,根据YSlow的要求,我的小站要从Grade B上升到Grade A怕是有些难度了。因为首页上加载了两个Flash,还有5个JS,拖慢了不少速度,等会有时间我研究下把这5个JS合并,或许会好些吧。我又查了下新 浪、网易、搜狐这样的大型门户网站,也不过Grade B甚至Grade C,我心理平衡一下,嘿嘿。

Continue reading gzip系列

数据仓库(DW)与操作型数据存储(ODS)

1 概述
系统应用集成中一般对各系统中数据分为两类

操作型数据:它 有细节化,分散化的特点

决策型数据:它 有综合化,集成化的特点

数据仓库概念的提出也把数据处理划分为了操作型处 理和分析型处理两种不同类型,从而建立起了DB-DW的两层体系结构。但是有很多情况,DB-DW的两层体系结构并不能涵盖企业所有的数据处理要求,比如 有些实时性决策问题,它要求获取数据周期不能太长,而且也需要一定程度的汇总。这样的问题可以借助于DB-DW的中间层ODS(操作数据存储)来解决。它 象DW一样是一种面向主题,集成的数据环境,又象操作型DB一样包含着全局一致的,细节的当前的数据。我们看下常用的几种系统应用集成需求:

我要了解企业目前的运转情况!(实时监控)

我要知道某地区近5年内的销售情况以制定未来的发展策 略!(决策支持)

我要知道哪些是值得发展的优质的顾客!(预测)

提供企业内部和外部的有用信息以支持中期或远期决策

提供事实的全局信息进行实时监控与临时决策

要满足上面所有的需求,不管是传统的OLTP系统 还是已经集成的数据仓库,都是很难完成任务的。由于这些原因,ODS应运而生。ODS可以看做是围绕主题进行动态整合的一种应用型体系结构,它有如下一些 特点:

从应用子系统获取数据

提供几乎精确到每秒的企业整体应用状态

数据一旦过期就将转入DW

实时决策与预警提示

使用者多为前端业务人员


    2 DW与ODS比 较:

数据仓库ODS
目的决策支持接近实时监控
共同点整合数据整合数据
面向主题面向主题
不同点静态数据
(延迟>24小时)
动态数据
(延迟>1秒)
历史数据当前数据
概括性数据细节化数据




    

实施方案实施结果优势缺陷
数据仓库(DW)企业能够分析DW中的历史数据,进行中远期的规划可以解决企业的决策需求不能满足企业的实时监控和实时业务需求
操作型数据存储(ODS)企业能够把握ODS中的当前综合数据,对企业的及时运行情况随时掌控可以满足企业的实时监控和实时业务需求
不能满足企业的中远期决策需求
DW+ODS(如下图)企业能够分析ODS中的当前综合数据,对企业当前运行情况进行宏观控制;能够分析DW中的历史数据,对未来进行合理规划既能把握实时的企业运作情况,采取及时的应对措施;又能把握历史纵向概况,进行远期战略规划

图1 ODS+DW方案


    4 三种类型的ODS:

类型一:以几秒为间隔的更新(非常贵、不常用、数 据整合能力弱)

类型二:以约1小时为间隔的更新(常用、数据整合 能力较强)

类型三:以约1天为间隔的更新(常用、数据整合能 力较强)

ODS技术的引入和应用,为企业在日常经营中进行 即时OLAP提供了一种解决方案使得企业无须建立一个“臃肿”的DW,就可以进行一些非战略性的的中层决策,来实现对企业的日常管理和控制,同时也能获得 较快的响应速度

Continue reading 数据仓库(DW)与操作型数据存储(ODS)

extjs 分页排序

extjs GridPanel 使用jsonstore的load来加载远程数据:

Ext.onReady(function() {
           var store = new Ext.data.JsonStore({
                       url : 'getRes.ax',//远程加载
                       root : 'rows',//告诉store,server返回json数据rows是本页的记录数组
                       totalProperty : 'count',//告诉store,server返回json数据中count表明总共记录数
                       remoteSort : true,//远程排序
                       fields : [{
                                   name : 'id',
                                   type : 'int'
                               }, {
                                   name : 'actived',
                                   type : 'bool'
                               }, {
                                   name : 'selected',
                                   type : 'bool'
                               }, {
                                   name : 'value',
                                   type : 'string'
                               }],
                       listeners : {
                           beforeload : function() {
                            //beforeloadr事件是添加参数的最好途径
//这里可以添加查询条件   
                               // can add the filter params at here
                               // store.setBaseParam('selected:bool',true);
                               // store.setBaseParam('actived:bool',true);
                               store.setBaseParam('ps', Ext.encode({
                                                   'selected' : true,
                                                   'actived' : true
                                               }));
//结合pagingtoolbar使用时,每次的分页排序,会向serversrvr传参数start[开始的行数],limit[需要的行数],sort[排序的字段],dir[排序方向]。


                           }
                       }
                   });

           var PAGESIZE = 2;

           var grid = new Ext.grid.GridPanel({
                       store : store,
                       bbar : new Ext.PagingToolbar({
                                   store : store,
                                   displayInfo : true,
                                   pageSize : PAGESIZE
                               }),
                       columns : [{
                                   header : 'actived',
                                   sortable : true,
                                   dataIndex : 'actived'
                               }, {
                                   header : 'selected',
                                   sortable : true,
                                   dataIndex : 'selected'
                               }, {
                                   header : 'value',
                                   sortable : true,
                                   dataIndex : 'value'
                               }],
                       columnLines : true,
                       viewConfig : {
                           forceFit : true,
                           emptyText : 'No data available'
                       },
                       stripeRows : true,
                       header : false
                   });

           store.load({
                       params : {
                           start : 0,
                           limit : PAGESIZE
                       }
                   });

           var vi = new Ext.Viewport({
                       layout : 'fit',
                       items : grid
                   });

           vi.show();
       });

Continue reading extjs 分页排序

Pagination


Total views.

© 2013 - 2019. All rights reserved.

Powered by Hydejack v6.6.1