【转】笑着学习笔记iBatis入门
根据官网上的开发指南,按照个人使用习惯,频度等整理的,没啥特别的东西。
笑着--胖胖兰学习笔记iBatis入门
一, iBatis简介
iBatis是一种数据库持续层的ORM框架。使用简单的XML配置文件将Java Bean映射成PreparedStatement的输入参数和ResultSet结果集。
在不是很复杂的情况下,我们 甚至可以使用HashMap而不是Java Bean来映射PreparedStatement的输入参 数和ResultSet结果集,从而节省开发时间与成本。 或者,我们可以使用一些辅助工具来帮助我们通过XML配置生成对应的Java Bean.
二, iBatis工作原理,流程
iBatis使用简单的XML描述文件将Java Bean,Map实现和基本数据类型的包装类(String,Integer等)映射成JDBC的PreparedStatement的输入参数 和ResultSet结果集。具体工作流程如下:
1.在sqlMapConfig的XML配置文件中进行数据库连接的配 置,XML配置文件名称任意,比如sql-map-config.xml
2.在sqlMapConfig的XML配置文件中引用sqlMap的XML配置文件
<sqlMap resource="examples/sqlmap/maps/Person1.xml" /> <sqlMap url="file:///c:/config/Customer.xml " /> |
3.在sqlMap的XML配置文件中进行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); |
5.SqlMapClient对象提供函数,函数的参数 对应替换sqlMap配置文件中的id,parameter等等属性,完成SQL文的执 行。具体参照iBatis的API
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文中对应的输入参数
基本数据类型与参数1对1,没啥匹配的问题。不过官 方的开发指南中强调参数要写成#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> |
以上,数据类型通过反射与对 应的属性类型自动匹配,极少数时候可能需要通过resultMap的javaType属性进行设定,参考后面关于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的数据类型(即int,double,float等) 赋值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的属性获得,但对于某些映射 (例如Map和XML 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_ID” select=”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> |
避 免N+1 Select(1: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> |
避 免N+1 Select(1: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>
1.Serializable可读写缓存 正 如您所知道的,只对当前Session有效的缓存对整体应用性能的提高作用有限。Serializable可读写缓存可以提高整体应用(而不仅仅是每个Session)的性能。这种缓存为每一个Session返回缓存对象不同的实例(复本)。因此每一个Session都可以安全修改返回的对象。不同之处在于,通常您希望从缓存中得到同一个对象,但这种情况下得到的是不同的对象。还有,每一个 缓冲在Serializable缓 存的对象都必须是Serializable的。 这意味着不能同时使用Serializable缓存和延迟加载,因为延迟加载代理不是Serializable的。想知道如何把Serializable缓存,延迟加载和联合查询结合起来使用,最好的方法是尝试。要使用Serializable缓 存,设置readOnly=“false”和serialize=“true”。缺省情况下,缓存是只读模式,不使用Serializable缓存。只读缓存不需要Serializable。
2.Type a.type=”MEMORY” MEMORY cache实现只认识一个<property>元素。这个名为“reference-type”属性的值必须是STRONG,SOFT和WEAK三者其一。这三个值分别对应于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> 上 面的例子中,根据参数bean“id”属性的不同情况,可创建两个可能的语句。如果参数“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()的值,属性的String或String.valueOf()值,是否为null或空(“”或size() < 1)。 |
<isNotEmpty> | 检查Collection.size()的值,属性的String或String.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> |
4.Iterate:这属性遍历整个集合,并为List集 合中的元素重复元素体的内容。
Iterate的属性:
prepend - 可被覆盖的SQL语句组成部分,添加在语句的前面(可选)
property - 类型为java.util.List的用于遍历的元素(必选)
open - 整个遍历内容体开始的字符串,用于定义括号(可选)
close -整个遍历内容体结束的字符串,用于定义括号(可选)
conjunction - 每次遍历内容之间的字符串,用于定义AND或OR(可选)
<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语句放在XML的CDATA区里面就可 以了。例 如:
<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.xml的namespace.id来查找对应 的sql文id,从而避免 这个问题。
二, 其他
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.配置文件:略