iBatis 在DAO层的用法很基础,和一般 JDBC 用法没太多的不同之处,主要是实现数据的持久化。它的优势是用法比较灵活,可以根据业务需要,写出适应需要的sql,其使用简单,只要会使用sql,就能使用该框架开发。下面我们主要学习一些关于iBatis的基础sql配置语法,稍复杂的语法将在下一章讨论。
在上一张我们讨论了如何搭建一个 iBatis 的开发环境,非常简单,导入相应的 jar 包,然后就可以开始享受框架的魅力了,这一章我们着重讲基础的 iBatis 语法,SqlMapClient这个类是我们通过 iBatis 操作数据库的关键类,它提供了我们连接数据库的接口,并提供了一系列访问数据库的接口方法,我们只要拿到了这个对象,就能实现对数据库的各种操作了。
本节要点:
一、SqlMapClient对象的常用方法
二、核心配置文件的说明
三、SQL配置文件简要用法
1、使用 iBatis 实现查询功能,即 select 的功能
2、使用 iBatis 实现更新功能,即 update 的功能
3、使用 iBatis 实现新增功能,即 insert 的功能
4、使用 iBatis 实现删除功能,即 delete 的功能
-------------------------- 一、SqlMapClient对象的常用方法 -------------------------------
1、queryForObject()
该方法主要从数据库中获取一条记录,并将它放到一个 java 对象中,主要有如下两种用法,第一种较为常用。
sqlMapClient.queryForObject(String id, Object parameter);
sqlMapClient.queryForObject(String id, Object parameter,Object result);
其中的id 是一个关联到sql配置文件的标示,parameter是sql语句的入参,后面雷同,不再详述。
需要注意的是,使用这个方法只能返回一条记录,如果返回记录超过一条,将抛出异常,所以我们需要限制返回结果只有一条记录。
2、queryForList()
该方法主要从数据库中获取一个List的 java 对象列表,返回的可以是一道多行,主要有如下两种用法:
sqlMapClient.queryForList(String id, Object parameter);
sqlMapClient.queryForList(String id, Object parameter,int skip,int size)
注意其中的第二种用法,它可以返回从 skip 的位置开始,并向后取 size 条数据。一般的分页功能可以通过它来实现。
3、queryForMap()
该方法用于从数据库获取一行或者多行组成的一个Map,它主要有如下两个本版的方法:
sqlMapClient.queryForMap(String id, Object parameter,String key);
sqlMapClient.queryForMap(String id, Object parameter,String key,String value);
需要指出的是,第一个方法返回的 Map 的 key 有方法中的第三个参数指定,具体取对象的哪个属性作为 key 可以指定,其 value 是一个具体的java 类;同样的,第二个方法与第一个方法的差别是其 map 的 value 也可以指定,且不再是java 对象,而是一个字符串String。
4、sqlMapClient.update();
该方法主要用于执行更新语句
sqlMapClient.update(String id, Object parameter)
5、sqlMapClient.insert()
该方法主要用于将数据插入到数据库中。
sqlMapClient.insert(String id, Object parameter)
6、sqlMapClient.delete()
该方法主要用于将数从数据库中删除。
sqlMapClient.delete(String id, Object parameter)
-------------------------- 二、核心配置文件的说明 -------------------------------
iBatis的核心配置文件,一般命名为SqlMapConfig.xml,当然我们也可以命名为其他的名字。这个文件称为核心配置文件,也叫主配置文件,包括数据库连接以及sql配置文件的引用都是在这个文件中完成的。下面我们看一下这个配置文件的具体元素。
<?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>
<!-- 1、资源文件引用 -->
<properties resource="db.properties"/>
<!-- 2、 全局配置管理-->
<settings
maxSession="20"
/>
<!-- 3、配置事务管理 -->
<transactionManager type="JDBC">
<!-- 配置数据源 -->
<dataSource type="SIMPLE">
<property name="JDBC.Driver" value="${driver}"/>
<property name="JDBC.ConnectionURL" value="${url}"/>
<property name="JDBC.Username" value="${user}"/>
<property name="JDBC.Password" value="${password}"/>
</dataSource>
</transactionManager>
<!-- 4、引用具体的 sql 配置文件 -->
<sqlMap resource="config/sqlmap-mapping-student.xml"/>
</sqlMapConfig>
我们可以看到主配置文件主要包含4大部分,下面分别讲这几个部分的作用。
1、资源文件应用部分,这个主要是让我们可以将一些信息写到资源文件中,然后再这个文件中通过引用这个资源文件即可访问资源文件中的数据信息,例如我们可以将数据库连接信息写到资源文件中,然后再这个文件中读取信息即可。
2、全局配置选项部分,这个部分的配置对整个项目来讲都是全局的,我们可以将一些全局的选项配置到这里面,例如数据是否使用缓存等信息
3、事务管理配置部分,这个部分主要配置数据库的事务管理,以及数据源的加载等信息。关于数据库的事务管理我们在本章最后讲解。
4、引入具体的sql配置文件,我们在整个项目中可能存在众多的sql配置文件,我们需要在这里对所有的sql配置文件进行注册引用,才能正常的使用。
-------------------------- 三、SQL配置文件简要用法 -------------------------------
看完了SqlMapClient的具体方法,那么在java代码中如何获取数据库中的数据就有了一个基本的认识,但是具体从数据中获得数据的具体配置还需要详细讨论,下面我们主要看一下sql的配置文件的用法。
一般的语法如下:
<sqlMap>
<何种语法 id="XXX" parameterClass="入参类型" resultClass="返回值的类型">
具体的SQL语句
</何种语法>
<sqlMap>
其中的"何种语法"主要包括的 insert、select、update、delete等基本语法,ID是我们与SqlMapClient交互的一个信号,这个ID决定我们代码中的程序读取sql配置文件中的哪个sql语句的对应关系。parameterClass指定的sql的入参类型,resultClass决定了sql语句最终的返回值类型。
下面分别举例说明。先附数据信息如下:
1、使用 iBatis 实现查询功能,即 select 的功能
sqlmap-mapping-student.xml:
<sqlMap>
<select id="test_select" parameterClass="java.lang.Integer" resultClass="com.test.bean.Student">
select name,sex from t_stu where id=#id#
</select>
<sqlMap>
--java代码如下:
SqlMapClient sqlMapClient = BaseDAO.getInstance();
try {
Student student = (Student) sqlMapClient.queryForObject("test_select",1);
System.out.println(student.getName());
} catch (SQLException e) {
e.printStackTrace();
}
我们可以看出,通过查询后返回的结果放到了一个 Student 实例中。
2、使用 iBatis 实现更新功能,即 update 的功能
sqlmap-mapping-student.xml:
<update id="test_update" parameterClass="com.test.bean.Student">
update t_stu set name=#name# where id=#id#
</update>
--java代码如下:
SqlMapClient sqlMapClient = BaseDAO.getInstance();
try {
Student student = new Student();
student.setId(3);
student.setName("修改后的姓名");
int k = sqlMapClient.update("test_update", student);
System.out.println("更新记录条数为:"+k);
} catch (SQLException e) {
e.printStackTrace();
}
执行更新后数据库记录如下:
3、使用 iBatis 实现新增功能,即 insert 的功能
sqlmap-mapping-student.xml:
<update id="test_insert" parameterClass="com.test.bean.Student">
insert into t_stu(name,sex) values(#name#,#sex#)
</update>
--java代码如下:
SqlMapClient sqlMapClient = BaseDAO.getInstance();
try {
Student student = new Student();
student.setName("新增学生测试");
student.setSex("男");
sqlMapClient.insert("test_insert", student);
System.out.println("新增学生成功");
} catch (SQLException e) {
e.printStackTrace();
}
新增学生成功:
4、使用 iBatis 实现删除功能,即 delete 的功能
sqlmap-mapping-student.xml:
<update id="test_delete" parameterClass="com.test.bean.Student">
delete from t_stu where id=#id#
</update>
--java代码如下
SqlMapClient sqlMapClient = BaseDAO.getInstance();
try {
Student student = new Student();
student.setId(10);
int k = sqlMapClient.delete("test_delete", student);
System.out.println("删除学生记录条数:"+k);
} catch (SQLException e) {
e.printStackTrace();
}
第10条记录成功删除。
--------------------------------------------------------------------------------
1、补充一个SQL配置文件中别名的使用方法
<!-- 给类定义别名,简化代码 -->
<typeAlias alias="student" type="com.test.bean.Student"></typeAlias>
<!-- 新增 -->
<update id="test_insert" parameterClass="student">
insert into t_stu(name,sex) values(#name#,#sex#)
</update>
我们谁也不愿意在SQL配置文件中写超长的全类路径,所以可以通过标签<typeAlias> 定义一个别名,然后直接使用这个别名即可达到简化的目的。
2、关于数据库的事务讲解:百度百科解释如下:
数据库事务
数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。 事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。一个逻辑工作单元要成为事务,必须满足所谓的ACID(原子性、一致性、隔离性和持久性)属性。事务是数据库运行中的一个逻辑工作单位,由DBMS中的事务管理子系统负责事务的处理。
事务的4个特性【ACID】:
原子性
(Atomic)(Atomicity)
事务必须是原子工作单元;对于其数据修改,要么全都执行,要么全都不执行。通常,与某个事务关联的操作具有共同的目标,并且是相互依赖的。如果系统只执行这些操作的一个子集,则可能会破坏事务的总体目标。原子性消除了系统处理操作子集的可能性。
一致性
(Consistent)(Consistency)
事务在完成时,必须使所有的数据都保持一致状态。在相关数据库中,所有规则都必须应用于事务的修改,以保持所有数据的完整性。事务结束时,所有的内部数据结构(如 B 树索引或双向链表)都必须是正确的。某些维护一致性的责任由应用程序开发人员承担,他们必须确保应用程序已强制所有已知的完整性约束。例如,当开发用于转帐的应用程序时,应避免在转帐过程中任意移动小数点。
隔离性
(Insulation)(Isolation)
由并发事务所作的修改必须与任何其它并发事务所作的修改隔离。事务查看数据时数据所处的状态,要么是另一并发事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看中间状态的数据。这称为隔离性,因为它能够重新装载起始数据,并且重播一系列事务,以使数据结束时的状态与原始事务执行的状态相同。当事务可序列化时将获得最高的隔离级别。在此级别上,从一组可并行执行的事务获得的结果与通过连续运行每个事务所获得的结果相同。由于高度隔离会限制可并行执行的事务数,所以一些应用程序降低隔离级别以换取更大的吞吐量。
持久性
(Duration)(Durability)
事务完成之后,它对于系统的影响是永久性的。该修改即使出现致命的系统故障也将一直保持。
另外,在事务处理中需要明白几个概念,事务的提交和回滚,提交是指整个流程走完,正常的将整个动作提交,这时候所有的操作都将真正的生效。回滚是指由于各种原因,事务需要回退到某个操作前得状态,对于回滚的这些操作,是不生效的。一般事务是自动提交的,我们可以根据需要,将事务设置成手动提交,然后在程序中一旦发生异常或者错误,就回滚事务,避免数据出现紊乱的情况。
在第五章中我们将详细讨论数据库的事务问题。