iBatis初体验

1.什么是iBatis
iBatis属于ORM范畴,但它仅相当于半个ORM,因为使用iBatis仍然要写SQL,而不是SQL全部由ORM工具自动生成,iBatis更关注SQL所需参数,以及SQL返回的结果集到POJO的映射。

优势:
1)应用的持久层操作的是数据对象,而非jdbc的ResultSet,减轻了持久层的工作量,并使代码更加清晰、简洁。
2)对于性能要求高的,可以针对SQL做优化,以达到最佳的数据库执行性能,使用iBatis更加灵活、自由,程序员都是向往自由滴。

劣势:
1)仍然需要手动写SQL语句。
2)无法保证数据库兼容,即无法跨数据库。


2.iBatis之Helloworld
数据库表 person:

CREATE TABLE `person` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
`sex` varchar(2) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
)

通过iBatis 2.0实现对person表的增删该查功能,下面是代码和配置文件。
代码目录截图:

[img]http://dl2.iteye.com/upload/attachment/0104/8545/5fe626a6-d574-3d9e-883f-a63b79cc710e.jpg[/img]


iBatis主配置文件:
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="org/frank1234/ibatis/helloworld/sqlMapConfig.properties"></properties>
<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}"/>
</dataSource>
</transactionManager>
<sqlMap resource="org/frank1234/ibatis/helloworld/person.xml"/>

</sqlMapConfig>


[color=red][b]注意其中的resource必须写相对于classpath的全路径。[/b][/color]
transactionManager中的type和dataSource中的type暂时不解释。


这里数据库配置信息,引用了另外一个配置文件sqlMapConfig.properties
sqlMapConfig.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/demo
username=root
password=frank1234


跟数据库表对应的数据对象:
Person类
public class Person {
private int id;
private String name;
private int age;
private String sex;

public Person(int id, String name, int age, String sex) {
this.id = id;
this.name = name;
this.age = age;
this.sex = sex;
}
[color=red][b] //这个是必须有,不是可以有。[/b][/color]
public Person() {
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getSex() {
return sex;
}

public void setSex(String sex) {
this.sex = sex;
}
public String toString(){
return "id="+id+",name="+name+",age="+age+",sex="+sex;
}
}


sqlMap配置文件:
person.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://www.ibatis.com/dtd/sql-map-2.dtd">
<sqlMap namespace="person">
<select id="getPerson" resultClass=" org.frank1234.ibatis.helloworld.Person">
select id,name,sex,age from person where id=#value#
</select>
<insert id="savePerson" parameterClass="org.frank1234.ibatis.helloworld.Person">
insert into person(name,sex,age) values(#name#,#sex#,#age#)
</insert>
<update id="updatePerson" parameterClass="org.frank1234.ibatis.helloworld.Person">
update person set name=#name#,sex=#sex#,age=#age# where id=#id#
</update>
<delete id="deletePerson" parameterClass="org.frank1234.ibatis.helloworld.Person">
delete from person where id=#id#
</delete>
</sqlMap>


iBatis通过Person对象的getter和setter方法完成入参的赋值,以及返回值到Person对象的封装。

获取SqlMapClient的工具类:
IBatisUtil类,其中使用了单例模式的双重校验锁。注意volatile变量和synchronized内部的if(sqlMap == null)判断。另外resource也是要写全路径。SqlMapClient是iBatis操作的核心。
public class IBatisUtil {
private static volatile SqlMapClient sqlMap;
public static SqlMapClient getSqlMap(){
if(sqlMap == null){
synchronized (IBatisUtil.class){
if(sqlMap == null){
try {
String resource = "org/frank1234/ibatis/helloworld/sqlMapConfig.xml";
Reader reader = Resources.getResourceAsReader(resource);
sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
return sqlMap;
}
}


测试类:
IBatisHelloworldMain类:
public class IBatisHelloworldMain {
public static void main(String[] args) throws Exception{
// save();
get();
// update();
// delete();

}
public static void get() throws Exception{
SqlMapClient client = IBatisUtil.getSqlMap();
Person person = (Person)client.queryForObject("getPerson",new Integer(2));
System.out.println(person);
}
public static void save() throws Exception{
SqlMapClient client = IBatisUtil.getSqlMap();
Person person = new Person();
person.setName("frank1234");
person.setAge(80);
person.setSex("男");
client.insert("savePerson",person);
}
public static void update() throws Exception{
SqlMapClient client = IBatisUtil.getSqlMap();
// client.startTransaction();
Person person = new Person();
person.setId(1);
person.setName("frank12345");
person.setSex("女");
person.setAge(60);
client.update("updatePerson", person);
}
public static void delete() throws Exception{
SqlMapClient client = IBatisUtil.getSqlMap();
Person person = new Person();
person.setId(1);
client.delete("deletePerson",person);
}
}


3.几点补充
3.1 如何在控制台输出SQL
log4j的级别改为debug级别。
可在控制台见到如下输出:
2015-01-02 10:55:52,571: {conn-100000} Connection
2015-01-02 10:55:52,573: {conn-100000} Preparing Statement: select id,name,sex,age from person where id=?
2015-01-02 10:55:52,602: {pstm-100001} Executing Statement: select id,name,sex,age from person where id=?
2015-01-02 10:55:52,602: {pstm-100001} Parameters: [2]
2015-01-02 10:55:52,602: {pstm-100001} Types: [java.lang.Integer]
2015-01-02 10:55:52,604: {rset-100002} ResultSet
2015-01-02 10:55:52,616: {rset-100002} Header: [id, name, sex, age]
2015-01-02 10:55:52,616: {rset-100002} Result: [2, frank1234, 男, 80]

3.2 别名
参见helloworld示例中的sqlmap文件
每个parameterClass="org.frank1234.ibatis.helloworld.Person"都得写全路径,很烦。
这个可以通过别名来解决:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://www.ibatis.com/dtd/sql-map-2.dtd">
<sqlMap namespace="person">
<typeAlias alias="person" type="org.frank1234.ibatis.helloworld.Person"/>
<select id="getPerson" resultClass="person" >
select id,name,sex,age from person where id=#value#
</select>
</sqlMap>


这下resultClass直接写成person就可以了。


3.3 命名空间
因为操作数据库通过sqlMap中定义的id来操作,这需要保证每个sqlMap中的id是唯一的,对于一个有很多人参与的大型项目,如果没有很好的规范和功能划分的话,很容易id重复,使用namespace可以解决这个问题。

首先:主配置文件中打开namespace,默认是关闭的
<sqlMapConfig>
<properties resource="org/frank1234/ibatis/helloworld/sqlMapConfig.properties"></properties>
<settings useStatementNamespaces="true"/>

</sqlMapConfig>


然后在sqlMap配置文件中配置namespace
<sqlMap namespace="[color=red][b]person[/b][/color]">
<typeAlias alias="person" type="org.frank1234.ibatis.helloworld.Person"/>
<insert id="[color=red][b]savePerson[/b][/color]" parameterClass="org.frank1234.ibatis.helloworld.Person">
insert into person(name,sex,age) values(#name#,#sex#,#age#)
</insert>
</select>
</sqlMap>


最后SqlMapClient操作的时候,比如对于之前的保存,需要写成:
client.insert("person.savePerson",person);

3.4 select的另一种方式
helloworld中的get()通过转型获取的Person对象,还有另外一种写法:
public static void get() throws Exception{
SqlMapClient client = IBatisUtil.getSqlMap();
Person person = new Person();
client.queryForObject("getPerson",new Integer(2),person);
System.out.println(person);
}


3.5 数据库字段和属性字段的对应
如果数据库字段的名字和对象属性的名字不一样,可通过as或者<ResultMap>元素来实现。
使用as更简洁。
例如:
<select id="getPerson" resultClass="person" >
select id,xingming as name,xingbie as sex from person where id=#value#
</select>


这样就实现了数据库字段名为xingming和xingbie,而对象中为name和sex的映射。

3.6 数据库连接的另外几种获取方式
helloworld中datasource的获取方式为SIMPLE。
另外还有DBCP和JNDI两种获取方式。
DBCP只是type不同,子元素同SIMPLE一样:
<dataSource type="DBCP">
<property name="JDBC.Driver" value="${driver}"/>
<property name="JDBC.ConnectionURL" value="${url}"/>
<property name="JDBC.Username" value="${username}"/>
<property name="JDBC.Password" value="${password}"/>
</dataSource>


JNDI方式,这样可以集成第三方的数据库连接池,比如使用tomcat+c3p0连接池:
<dataSource type="JNDI">
<property name="DataSource" value="java:comp/env/xxxDataSource"/>
</dataSource>


3.7 获取Connection对象
代码示例:
SqlMapClient client = IBatisUtil.getSqlMap();
SqlMapSession session = client.openSession();
Connection conn = session.getCurrentConnection();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值