2ibatis语义

1SqlMapClient基本操作实例
XmlSqlMapClientBuilder
XmlSqlMapClientBuilder是ibatis 2.0之后版本新引入的组件,用以替代1.x版本中的XmlSqlMapBuilder。其作用是根据配置文件创建SqlMapClient实例。


SqlMapClient
SqlMapClient是ibatis的核心组件,提供数据操作的基础平台。SqlMapClient可通过XmlSqlMapClientBuilder创建:
String resource ="com/ibatis/sample/SqlMapConfig.xml";
Reader reader;
reader = Resources.getResourceAsReader(resource);
XmlSqlMapClientBuilder xmlBuilder =
new XmlSqlMapClientBuilder();
SqlMapClient sqlMap = xmlBuilder.buildSqlMap(reader);
"com/ibatis/sample/SqlMapConfig.xml"指明了配置文件在CLASSPATH中的相对路径。XmlSqlMapClientBuilder通过接受一个Reader类型的配置文件句柄,根据配置参数,创建SqlMapClient实例。
数据写入操作(insert, update, delete):
sqlMap.startTransaction();
Product product = new Product();
product.setId (1);
product.setDescription (“Shih Tzu”);
int rows = sqlMap.insert (“insertProduct”, product);
sqlMap.commitTransaction();


数据查询(select)
sqlMap.startTransaction();
Integer key = new Integer (1);
Product product = (Product)sqlMap.queryForObject("getProduct", key);
sqlMap.commitTransaction();


在指定对象中存放查询结果(select)
sqlMap.startTransaction();
Customer customer = new Customer();
sqlMap.queryForObject(“getCust”, parameterObject, customer);
sqlMap.queryForObject(“getAddr”, parameterObject, customer);
sqlMap.commitTransaction();


执行批量查询(select)
sqlMap.startTransaction();
List list = sqlMap.queryForList (“getProductList”, null);
sqlMap.commitTransaction();


关于AutoCommit
//没有预先执行startTransaction时,默认为auto_commit模式
int rows = sqlMap.insert (“insertProduct”, product);


查询指定范围内的数据
sqlMap.startTransaction();
List list = sqlMap.queryForList (“getProductList”, null, 0, 40);
sqlMap.commitTransaction();


分页查询(select)
PaginatedList list =
sqlMap.queryForPaginatedList (“getProductList”, null, 10);
list.nextPage();
list.previousPage();


结合RowHandler进行查询(select)
public class MyRowHandler implements RowHandler {
public void handleRow (Object object, List list) throws
SQLException {
Product product = (Product) object;
product.setQuantity (10000);
sqlMap.update (“updateProduct”, product);
}
}
sqlMap.startTransaction();
RowHandler rowHandler = new MyRowHandler();
List list = sqlMap.queryForList (“getProductList”, null,
rowHandler);
sqlMap.commitTransaction();


基于Map的批量查询(select)
sqlMap.startTransaction();
Map map = sqlMap.queryForMap (“getProductList”, null,
“productCode”);
sqlMap.commitTransaction();
Product p = (Product) map.get(“EST-93”);


2ibatis高级特性
ibatis 中,提供了Statement 嵌套支持,通过Statement 嵌套,我们即可实现关联数据的操作。
一对多关联
下面的例子中,我们首选读取t_user 表中的所有用户记录,然后获取每个用户对应的所有地址信息。
配置文件如下:
<sqlMap namespace="User">
<typeAlias alias="user" type="com.ibatis.sample.User"/>
<typeAlias alias="address" type="com.ibatis.sample.Address"/>
<resultMap id="get-user-result" class="user">
<result property="id" column="id"/>
<result property="name" column="name"/>
<result property="sex" column="sex"/>
<result property="addresses" column="id" select="User.getAddressByUserId"/>
</resultMap>


<select id="getUsers"
parameterClass="java.lang.String"
resultMap="get-user-result">
<![CDATA[
select
id,
name,
sex
from t_user
where id = #id#
]]>
</select>


<select id="getAddressByUserId"
parameterClass="int"
resultClass="address">
<![CDATA[
select
address,
zipcode
from t_address
where user_id = #userid#
]]>
</select>
</sqlMap>


对应代码:
String resource ="com/ibatis/sample/SqlMapConfig.xml";
Reader reader;
reader = Resources.getResourceAsReader(resource);
XmlSqlMapClientBuilder xmlBuilder = new XmlSqlMapClientBuilder();
sqlMap = xmlBuilder.buildSqlMap(reader);
//sqlMap系统初始化完毕
List userList = sqlMap.queryForList("User.getUsers", "");
for (int i = 0; i < userList.size(); i++) {
User user = (User)userList.get(i);
System.out.println("==>" + user.getName());
for (int k = 0; k < user.getAddresses().size(); k++) {
Address addr = (Address) user.getAddresses().get(k);
System.out.println(addr.getAddress());
}
}
这里通过在resultMap 中定义嵌套查询getAddressByUserId,我们实现了关联数据的读取。


一对一关联
一对一关联是一对多关联的一种特例。对于这种情况,我们可以采用一次Select两张表的方式,避免这样的性能开销(假设上面示例中,每个User 只有一个对应的Address记录):
<resultMap id="get-user-result" class="user">
<result property="id" column="id"/>
<result property="name" column="name"/>
<result property="sex" column="sex"/>
<result property="address" column="t_address.address"/>
<result property="zipCode" column="t_address.zipcode"/>
</resultMap>
<select id="getUsers"
parameterClass="java.lang.String"
resultMap="get-user-result">
<![CDATA[
select *
from t_user,t_address
where t_user.id=t_address.user_id
]]>
</select>
与此同时,应该保证User 类中包含address和zipCode两个String型属性




*****************************
3ibatis in Spring


我们在Spring中采用c3p0数据库连接池:首先是在lib下增加c3p0-0.9.1.2.jar包和相应的连接数据库的包oraclejdbc.jar。然后在applicationContext.xml中增加如下配置
<bean id="dataSource"  class="com.mchange.v2.c3p0.ComboPooledDataSource"  destroy-method="close">  
  <property name="driverClass"  value="oracle.jdbc.OracleDriver" />  
        <property name="jdbcUrl"  value="jdbc:oracle:thin:@60.213.41.74:1521:office" />  
        <property name="user" value="lygs" />  
        <property name="password" value="123456" />  
        <!--当连接池中的连接用完时,C3P0一次性创建新连接的数目-->  
        <property name="acquireIncrement" value="10" />  
        <!-- 定义在从数据库获取新连接失败后重复尝试获取的次数,默认为30-->  
        <property name="acquireRetryAttempts" value="100" />  
        <!-- 两次连接中间隔时间,单位毫秒,默认为1000 -->  
        <property name="acquireRetryDelay" value="1000" />  
        <!-- 连接关闭时默认将所有未提交的操作回滚。默认为false -->  
        <property name="autoCommitOnClose" value="false" />  
        <!-- 获取连接失败将会引起所有等待获取连接的线程抛出异常。但是数据源仍有效保留,并在下次调   
用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试获取连接失败后该数据源将申明已断开并永久关闭。默认为 false; -->  
        <property name="breakAfterAcquireFailure" value="false"/>  
        <!--  
当连接池用完时客户端调用getConnection()后等待获取新连接的时间,超时后将抛出SQLException,如设为0则无限期等待。单位毫秒,默认为0;  
-->  
        <property name="checkoutTimeout" value="0" />  
        <!-- 始化时创建的连接数,应在minPoolSize与maxPoolSize之间取值。默认为3;-->  
        <property name="initialPoolSize" value="20" />  
        <!-- 最大空闲时间,超过空闲时间的连接将被丢弃。为0或负数则永不丢弃。默认为0; -->  
        <property name="maxIdleTime" value="10000" />  
        <!-- 接池中保留的最大连接数。默认为15-->  
        <property name="maxPoolSize" value="40" />  
        <!-- JDBC的标准参数,用以控制数据源内加载的PreparedStatement数量。但由于预缓存的Statement属   
于单个Connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素,如果maxStatements与   
maxStatementsPerConnection均为0,则缓存被关闭。默认为0; -->  
        <property name="maxStatements" value="0" />  
        <!-- 连接池内单个连接所拥有的最大缓存Statement数。默认为0;  -->  
        <property name="maxStatementsPerConnection" value="0" />  
        <!--C3P0是异步操作的,缓慢的JDBC操作通过帮助进程完成。扩展这些操作可以有效的提升性能,通过多线程实现多个操作同时被执行。默认为3;  
-->  
        <property name="numHelperThreads" value="3" />  
        <!-- 用户修改系统配置参数执行前最多等待的秒数。默认为300; -->  
        <property name="propertyCycle" value="600" />  
    </bean>
这样Spring中就整合了c3p0。
另外我们可以把c3p0连接数据库用到的driverClassName,url,username,password放到一个property文件中。如:
jdbc.driverClassName = oracle.jdbc.driver.OracleDriver
jdbc.url = jdbc:oracle:thin:@10.0.0.12:1521:dgzz
jdbc.username = dgzz
jdbc.password = dgzz


然后再Spring的applicationContext.xml配置一个<bean>加载这个文件,如果有多个properties文件就有多个<value></value>:
<!-- (in this case, JDBC related properties) -->
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>WEB-INF/conf/database/jdbc.properties</value>
                                <value>WEB-INF/conf/url.properties</value>
</list>
</property>
</bean>


那么对于在c3p0的配置,可以改成如下形式,${jdbc.driverClassName}表示引用property文件中的jdbc.driverClassName属性的值。
<property name="driverClass">
<value>${jdbc.driverClassName}</value>
</property>
<property name="jdbcUrl">
<value>${jdbc.url}</value>
</property>
<property name="user">
<value>${jdbc.username}</value>
</property>
<property name="password">
<value>${jdbc.password}</value>
</property>






下面是在Spring中将ibatis整合进来(需要ibatis-2.3.4.726.jar)。配置文件如下:
由于前面我们使用的是c3p0连接池,所以我们不必再配置<bean id="dataSource">.....</bean>,这里仍然给出仅做参考,我们只需要在applicationContext.xml中导入ibatis的配置文件。


applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!--可不配置dataSource,因为上面的Spring配置文件中已经采用了c3p0-->
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName">
<value>net.sourceforge.jtds.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:jtds:sqlserver://127.0.0.1:1433/Sample</value>
</property>
<property name="username">
<value>test</value>
</property>
<property name="password">
<value>changeit</value>
</property>
</bean>


<!--导入配置ibatis配置文件sqlMapConfig.xml-->
<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation" value="WEB-INF/conf/ibatis/SqlMapConfig.xml" />
<!--
由于我们已经在applicationContext.xml中配置了数据源,所以不需要在ibatis配置文件sqlMapConfig.xml在配置数据源,但是需要将我们配置的数据元素注入进来,以便ibatis使用,所以需要下面这句
-->
<property name="dataSource" ref="dataSource" />
</bean>


<!--  配置事务 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactio
nManager">
<property name="dataSource">
<ref local="dataSource"/>
</property>
</bean>




<bean id="userDAO" class="net.xiaxin.dao.UserDAO">
<!--
这里的dataSource的配置可以省略,因为在上面的spring中已经配置了dataSource。
<property name="dataSource">
<ref local="dataSource" />
</property>
-->
<!-- 必须配置sqlMapClient或sqlMapClientTemplate,这里是sqlMapClient,将在UserDAO中使用的。 -->
<property name="sqlMapClient">
<!--使用上面已经配置的sqlMapClient-->
<ref local="sqlMapClient" />
</property>
</bean>


<!-- 事务代理 -->
<bean id="userDAOProxy"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref bean="transactionManager" />
</property>
<property name="target">
<ref local="userDAO" />
</property>
<property name="transactionAttributes">
<props>
<prop key="insert*">PROPAGATION_REQUIRED</prop>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
</beans>
sqlMapClient节点
sqlMapClient节点实际上配置了一个sqlMapClient的创建工厂类。configLocation属性配置了ibatis映射文件的名称。


transactionManager节点
transactionManager采用了Spring中的DataSourceTransactionManager。


userDAO节点
UserDAO需要配置两个属性,sqlMapClient和DataSource,sqlMapClient将从指定的DataSource中获取数据库连接。


对于ibatis的配置文件sqlMapConfig.xml,并在ibatis的配置文件sqlMapConfig.xml中指定ibatis的映射文件。这一步之前已将做过。可以参考之前的。映射文件user.xml的部分内容
<sqlMap namespace="User">
<typeAlias alias="user" type="net.xiaxin.dao.entity.User" />
<insert id="insertUser" parameterClass="user">
INSERT INTO users ( username, password) VALUES ( #username#,
#password# )
</insert>
</sqlMap>


UserDAO.java:
public class UserDAO extends SqlMapClientDaoSupport implements
IUserDAO {
public void insertUser(User user) {
//调用映射文件的"inserUser"来完成插入
getSqlMapClientTemplate().update("insertUser", user);
}
}
SqlMapClientDaoSupport(如果使用ibatis 1.x版本,对应支持类是SqlMapDaoSupport)是Spring中面向ibatis的辅助类,它负责调度DataSource、SqlMapClientTemplate(对应ibatis 1.x版本是SqlMapTemplate)完成ibatis操作,而DAO则通过对此类进行扩展获得上述功能。上面配置文件中针对UserDAO的属性设置部分,其中的属性也是继承自于这个基类。
SqlMapClientTemplate对传统SqlMapClient调用模式进行了封装,简化了上层访问代码。SqlMapClientTemplate几乎所有的方法当发生异常时都会抛出DataAccessException。




上面的DAO继承了SqlMapClientDaoSupport,在其类中可以通过getSqlMapClientTemplate()获得SqlMapClientTemplate实例;也可以不继承它,这样我们需要在applicationContext.xml为配置SqlMapClientTemplate,并在Dao中手动注入SqlMapClientTemplate。
<bean id="sqlMapClientTemplate" class="org.springframework.orm.ibatis.SqlMapClientTemplate">
//sqlMapClient在上面的applicationContext.xml中已经配置
<property name="sqlMapClient" ref="sqlMapClient"/>
</bean>
不继承了SqlMapClientDaoSupport对应的Dao代码:
public class UserDAO implements IUserDAO {
//手动注入SqlMapClientTemplate实例
@Resource(name="hibernateTemplate")
SqlMapClientTemplate sqlMapClientTemplate;


public void insertUser(User user) {
//调用映射文件的"inserUser"来完成插入
sqlMapClientTemplate.update("insertUser", user);
}
}




测试代码:
InputStream is = new FileInputStream("Ibatis-Context.xml");
XmlBeanFactory factory = new XmlBeanFactory(is);
IUserDAO Iuserdao = (IUserDAO)factory.getBean("userDAOProxy");
User user = new User();
user.setUsername("Sofia");
user.setPassword("mypass");
Iuserdao.insertUser(user);
这里使用了接口IUserDAO,它调用了该接口实现类的insertUser()方法,所以在Spring需要为该接口注入它的实现类。
    <bean id="Iuserdao" class="com.dao.UserDao">
       <property name="sqlMapClient">
  <ref local="sqlMapClient" />
</property>
</bean>




对比前面ibatis 程序代码,我们可以发现UserDAO.java 变得异常简洁,这也正是
Spring Framework为我们带来的巨大帮助。


********************
4关于SqlMapClientDaoSupport
HibernateDaoSupport是Spring对Hibernate的支持,而SqlMapClientDaoSupport是Spring对 ibatis的支持。SqlMapClientDaoSupport类针对iBATIS的DAO支持类,像Spring提供的其他DAO支持类一样,它也是作为一个父类让 DAO实现来继承的.


iBATIS API的核心是com.ibatis.sqlmap.client.SqlMapClient接口。SqlMapClient大致相当于 Hibernate的Session或JPA的EntityManager,用于执行全部的数据访问操作。不幸的是,iBATIS具有很多与JDBC、 Hibernate(3.0之前)和JPA一样的问题。不仅如此,使用iBATIS实现存留的程序还需要管理会话。而这些会话管理代码不过是样板代码而已,与保存对象到数据库的主要目标没有太大联系。另外,SqlMapClient的存储方法在发生错误时会抛出java.sql.SQLException。前面我们已经介绍过,SQLException既是一种必检异常,又过于范范而不便于使用。


Spring解决iBATIS会话管理和异常处理问题的答案是SqlMapClientTemplate。与本章前面介绍过的其他模板类似,SqlMapClientTemplate包裹了一个SqlMapClient来透明地打开和关闭会话,还捕获抛出的SQLException。


SqlMapClientTemplate可以在Spring的applicationContext.xml文件中进行配置:
<bean id="sqlMapClientTemplate" class="org.springframework.orm.ibatis.SqlMapClientTemplate">
<!--配置sqlMapClientTemplate的sqlMapClient,指定下面已经配置的sqlMapClient-->
<property name="sqlMapClient" ref="sqlMapClient"/>
</bean>


<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation">
<value>WEB-INF/SqlMapConfig.xml</value>
</property>
</bean>
然后上面配置的sqlMapClientTemplate,就可以在对DAO类的配置中使用。如:
<bean id="userDAO" class="net.xiaxin.dao.UserDAO">
<!--
这里的dataSource的配置可以省略,因为在上面的spring中已经配置了dataSource。
<property name="dataSource">
<ref local="dataSource" />
</property>
-->
<!-- 必须配置sqlMapClient或sqlMapClientTemplate,这里是sqlMapClientTemplate,将在UserDAO中使用的。 -->
<property name="sqlMapClientTemplate">
<!--使用上面已经配置的sqlMapClientTemplate-->
<ref local="sqlMapClientTemplate" />
</property>
</bean>


SqlMapClientDaoSupport的方法:
getDataSource(),返回DAO使用的JDBC DataSource。返回的是javax.sql.DataSource类型。


setDataSource(javax.sql.DataSource dataSource),设置DAO使用的JDBC DataSource。


getSqlMapClient(),返回iBatis数据库层的SqlMap这个模板工程。


setSqlMapClient(com.ibatis.sqlmap.client.SqlMapClient,sqlMapClient),设置iBatis数据库层的SqlMap。


getSqlClientTemplate(),返回DataSource中的SqlMapClientTemplate实例,我们的DAO类只要继承SqlMapClientDaoSupport就可以在DAO类中直接调用getSqlClientTemplate()获得SqlMapClientTemplate实例。


getSqlClientTemplate(SqlMapClientTemplate sqlMapClientTemplate),设置DAO中的jdbcTemplate。


SqlMapClientTemplate的方法:
构造方法:
SqlMapClientTemplate() 
SqlMapClientTemplate(javax.sql.DataSource dataSource, com.ibatis.sqlmap.client.SqlMapClient sqlMapClient) 


实例方法:
下面的statementName是java.lang.String类型,parameterObject是一个java.lang.Object类型。
int delete(statementName,parameterObject),表示执行ibatis映射文件中的id为statementName的删除操作,传递的给此操作的参数是parameterObject。


java.lang.Object insert(statementName,parameterObject),表示执行ibatis映射文件中的id为statementName的插入操作,传递给此操作的参数是parameterObject。


int update(String statementName,Object parameterObject),表示指定ibatis映射文件中id为statementName的更新操作,传递给此操作的参数是parameterObject。


update(String statementName,Object parameterObject,int requiredRowsAffected)


java.util.List queryForList(statementName,parameterObject),表示执行ibatis映射文件中的id为statementName的查询操作,传递给此操作的参数为parameterObject。


java.util.List queryForList(statementName,parameterObject,int skipResults,int max Results)


Map queryForMap(statement,parameterObject,String keyProperty)


Map queryForMap(statement,parameterObject,String keyProperty,String valueProperty)


Object queryForObject(statementName,parameterObject)


Object queryForObject(statementName,parameterObject,Object resultObject)


DataSource getDataSource(),返回数据源。
SqlMapClient getSqlMapClient(),返回SqlMapClient。
volid setSqlMapClient(SqlMapClient sqlMapClient),设置ibatis数据库层的sqlMapClient。





























  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值