iBatis是Apcahe的一个开源项目,10年由Google托管后,改名为mybatis
iBatis和hibernate一样是一种ORM(对象关系映射)的框架,不同之处在于Hibernate是提供了全面的数据库封装机制的全自动化ORM实现,实现了POJO和数据库表之间的映射,以及SQL的自动的生成和执行。而iBatis是一种办自动化的实现,着力于POJO和SQL之间的映射,也就是说iBatis并不会为程序员在运行期自动生成SQL执行,具体的SQL需要程序员自己编写,然后通过配置映射文件,将SQL所需的参数,以及返回的结果字段映射到指定的POJO.
iBatis以SQL开发的工作量和数据库移植性上差为代价,为系统设计提供了更大的自由空间。
下面就来实际操作一个iBatis的实例
首先是搭建iBatis的开发环境:导入jar包ibatis-2.3.4.726.jar和ojdbc14.jar
然后创建数据库表和添加数据
数据库语句
create table userinfo(
id int primary key,
name varchar2(50),
score varchar2(50)
);
Insert into users values(1,’唐伯虎’,’10’);
Insert into users values(2,’点’,’20’);
Insert into users values(3,’秋香’,’30’);
-- Create sequence
create sequence USERINFO_ID
minvalue 1
maxvalue 999999999999999999999999999
start with 1
increment by 1
cache 20;
package cn.entityy;
public class User {
private int id;
private String name;
private String score;
public String getScore() {
return score;
}
public void setScore(String score) {
this.score = score;
}
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 User(int id, String name,String score) {
super();
this.id = id;
this.name = name;
this.score=score;
}
public User(){
super();
}
}
SqlMapConfig-xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMapConfig PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
<sqlMapConfig>
<!-- 参数说明:
cacheModelsEnabled 是否启用SqlMapClient 上的缓存机制。建议设为"true"
enhancementEnabled:是否针对POJO 启用字节码增强机制以提升getter/setter 的调用效能,避免使用Java
Reflect 所带来的性能开销。同时,这也为Lazy Loading 带来了极大的性能提升。建议设为"true"
lazyLoadingEnabled: 启用或禁用SqlMapClient的所有延迟加载。调试程序时使用。 建议设为"true"
maxRequests: 同时执行SQL语句的最大线程数。大于这个值的线程将阻塞直到另一个线程执行完成。 不同的DBMS有不同的限制值,但任何数据库都有这些限制。通常这个值应该至少是
maxTransactions的10倍,并且总是大于maxSessions和maxTranactions。 减小这个参数值通常能提高性能。
maxSessions: 同一时间内活动的最大session数。一个session可以是代码请求的显式session, 也可以是当线程使用SqlMapClient实例(即执行一条语句)自动获得的session。
它应该总是大于或等于maxTransactions并小于maxRequests。减小这个参数值通常能 减少内存使用。
maxTransactions: 同时进入SqlMapClient.startTransaction()的最大线程数。大于这个值的线程将阻塞 直到另一个线程退出。不同的DBMS有不同的限制值,但任何数据库都有这些限制。这个
参数值应该总是小于或等于maxSessions并总是远远小于maxRequests。减小这个参数值 通常能提高性能。
useStatementNamespaces:
如果启用本属性,必须使用全限定名来引用mapped statement。Mapped statement的 全限定名由sql-map的名称和mapped-statement的名称合成,例如
queryForObject(“sqlMapName.statementName”) -->
<settings cacheModelsEnabled="true" lazyLoadingEnabled="true"
enhancementEnabled="true" />
<!-- 配置数据库连接信息 -->
<transactionManager type="JDBC">
<dataSource type="SIMPLE">
<property name="JDBC.Driver" value="oracle.jdbc.driver.OracleDriver" />
<property name="JDBC.ConnectionURL" value="jdbc:oracle:thin:@localhost:1521:orcl" />
<property name="JDBC.Username" value="scott" />
<property name="JDBC.Password" value="tiger" />
</dataSource>
</transactionManager>
<sqlMap resource="cn/entityy/sqlmap-user.xml" />
</sqlMapConfig>
通过<insert>、<delete>、<update>、
<select>四个节点,我们分别定义了针对TUser 对象的增删改查操作
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap
PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap>
<!-- typeAlias标签是设置别名用的 声明别名后,在文件的后续部分可以直接使用别名
而不用再给出完整类型了,非常方便 -->
<typeAlias alias="User" type="cn.entityy.User"/>
<!-- 返回值参数也同样有两种类型,一种是对象类型resultClass一种是resultMap
当结果集列名和类属性名完全对应的时候,则应该使用resultClass来指定查询结果类型。当然有些列明不对应,可以在sql中使用as重命名达到一致的效果。
当查询结果列名和类属性名对应不上的时候,应该选择 resultMap指定查询结果集类型。否则,则查询出来填充的对象属性为空(数字的为0,对象的为null)。
-->
<resultMap class="User" id="getAllUser" />
<!-- cacheModel 节点定义了本映射文件中使用的Cache 机制:
. flushInterval :设定缓存有效期,如果超过此设定值,则将此CacheModel 的缓存清空。
. size:本CacheModel 中最大容纳的数据对象数量。
. flushOnExecute:指定执行特定Statement 时,将缓存清空。如updateUser 操作将更新数据库中的用户信息,
这将导致缓存中的数据对象与数据库中的实际数据发生偏差,因此必须将缓存清空以避免脏数据的出现。
-->
<cacheModel type="LRU" id="userCache">
<flushInterval hours="24"/>
<flushOnExecute statement="updateUser"/>
<property name="size" value="1000"/>
</cacheModel>
<!-- 查询语句 -->
<select id="getAllUser" resultClass="User" cacheModel="userCache">
select * from userinfo
</select>
<!-- parameterClass表示参数的内容 -->
<!-- #表示这是一个外部调用的需要传进的参数,可以理解为占位符 -->
<!-- 通过<![CDATA[……]]>节点,可以避免SQL 中与XML 规范相冲突的字符对 XML 映射文件的合法性造成影响-->
<select id="getUserById" resultClass="User" parameterClass="int" cacheModel="userCache">
<![CDATA[
select * from userinfo
]]>
<dynamic prepend="where">
<isNotEmpty >
id= #id#
</isNotEmpty>
</dynamic>
</select>
<!-- 新增用户对象 -->
<!-- 这里需要说明一下不同的数据库主键的生成,对各自的数据库有不同的方式: -->
<!-- mysql:SELECT LAST_INSERT_ID() AS VALUE -->
<!-- mssql:select @@IDENTITY as value -->
<!-- oracle:SELECT STOCKIDSEQUENCE.NEXTVAL AS VALUE FROM DUAL -->
<!-- 还有一点需要注意的是不同的数据库生产商生成主键的方式不一样,有些是预先生成 (pre-generate)主键的,如Oracle和PostgreSQL。
有些是事后生成(post-generate)主键的,如MySQL和SQL Server 所以如果是Oracle数据库,则需要将selectKey写在insert之前 -->
<!-- 1. dual 确实是一张表.是一张只有一个字段,一行记录的表.
2.习惯上,我们称之为'伪表'.因为他不存储主题数据.
3. 他的存在,是为了操作上的方便.因为select 都是要有特定对象的. -->
<insert id="saveUser" parameterClass="User">
<selectKey resultClass="int" keyProperty="id">
select userinfo_id.nextval as id from dual
</selectKey>
<![CDATA[
insert into userinfo values(#id#,#name#,#score#)
]]>
</insert>
<!-- 删除用户对象 -->
<delete id="deleteUser" parameterClass="int">
<![CDATA[
delete from userinfo where id=#id#
]]>
</delete>
<!-- 更新用户对象 -->
<update id="updateUser" parameterClass="User">
<![CDATA[
update userinfo set name=#name#,score=#score# where id=#id#
]]>
</update>
</sqlMap>
package cn.dao;
import java.util.List;
import cn.entityy.User;
public interface UserDao {
public List<User> getAllUser();
public User getUserById(int id);
public void delete(int id);
public void save(User user);
public void update(User user);
}
package cn.impl;
import java.io.IOException;
import java.io.Reader;
import java.sql.SQLException;
import java.util.List;
import com.ibatis.common.resources.Resources;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapClientBuilder;
import cn.dao.UserDao;
import cn.entityy.User;
public class UserImpl implements UserDao {
private static SqlMapClient sqlmapclient=null;
static{
try {
Reader reader=Resources.getResourceAsReader("SqlMapConfig.xml");
sqlmapclient=SqlMapClientBuilder.buildSqlMapClient(reader);
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public List<User> getAllUser() {
try {
return sqlmapclient.queryForList("getAllUser");
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
@Override
public User getUserById(int id) {
try {
return (User) sqlmapclient.queryForObject("getUserById",id);
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
@Override
public void delete(int id) {
try {
sqlmapclient.delete( "deleteUser",id);
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
public void save(User user) {
try {
sqlmapclient.insert("saveUser", user);
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
public void update(User user) {
try {
sqlmapclient.update("updateUser", user);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package cn.test;
import java.util.List;
import cn.entityy.User;
import cn.impl.UserImpl;
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
UserImpl ui=new UserImpl();
ui.delete(4);
User u=new User();
u.setName("点");
u.setScore("20");
ui.save(u);
User uu=ui.getUserById(3);
uu.setName("秋香姐");
uu.setScore("90");
ui.update(uu);
List<User> list=ui.getAllUser();
for (User user : list) {
System.out.println(user.getId()+user.getName()+user.getScore());
}
User user=ui.getUserById(3);
System.out.println(user.getId()+user.getName()+user.getScore());
}
}
另外ibatis还支持动态定制SQL语句,详细操作可参考别的文章