Ibatis开发要点

来源:互联网 发布:采购管理erp软件 编辑:程序博客网 时间:2024/05/22 14:10

Ibatis提供了一种半自动化的O/R Mapping实现框架。它以牺牲工作量和移植性的代价换取了SQL语句设计的自由性和可优化性。

 

典型Ibatis配置文件
<?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>
 <settings cacheModelsEnabled="true"            //是否开启缓存
  enhancementEnabled="false"                        //是否开启字节码增强,提高get/set调用性能
  lazyLoadingEnabled="true"                            //是否开启延迟加载
  errorTracingEnabled="true"                            //是否启用错误日志
  maxRequests="32"                                         //最大并发请求
  maxSessions="10"                                          //最大允许并发SqlMapClient数
  maxTransactions="5"                                      //最大并发事务数
  useStatementNamespaces="false" />            //是否使用statment命名空间

 <transactionManager type="JDBC">                //传统JDBC事务支持
  <dataSource type="SIMPLE">                         //简单数据库连接池,对应SimpleDataSourceFactory
   <property name="JDBC.Driver" value="com.mysql.jdbc.Driver" />
   <property name="JDBC.ConnectionURL" value="jdbc:mysql://localhost:3306/mysql" />
   <property name="JDBC.Username" value="root" />
   <property name="JDBC.Password" value="password" />
   <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>

 <!-- JNDI
 <transactionManager type="JDBC">
  <dataSource type="JNDI">                   //使用J2EE容器实现DataSource,对应实现类JndiDataSourceFactory
   <property name="DataSource" value="java:comp/env/jdbc/myDataSource" />
  </dataSource>
 </transactionManager>-->
 <!-- JTA
 <transactionManager type="JTA">       //使用容器提供的JTA服务实现全局事务管理
  <property name="UserTransaction" value="java:/ctx/con/UserTransaction" />
  <dataSource type="JNDI">
   <property name="DataSource" value="java:comp/env/jdbc/myDataSource" />
  </dataSource>
 </transactionManager> -->
 
 <sqlMap resource="com/ibatis/ao/User.xml" />
</sqlMapConfig>

 

User模型类

public class User implements Serializable{
 private Integer id;
 private String name;
 private Integer sex;
 
 public User(){}
 
 public User(Integer id,String name,Integer sex){
  this.id=id;
  this.name=name;
  this.sex=sex;
 }

 public Integer getId() {
  return id;
 }

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

 public String getName() {
  return name;
 }

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

 public Integer getSex() {
  return sex;
 }

 public void setSex(Integer sex) {
  this.sex = sex;
 }
}

 

模型类映射文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://toolkit.alibaba-inc.com/dtd/ibatis/sql-map-2.dtd">
<sqlMap namespace="User">
 <typeAlias alias="user" type="com.ibatis.ao.User" />       //设置映射路径
 
 <!-- 模块配置 -->
 <cacheModel id="userCache" type="LRU">                //设置缓存类型
  <flushInterval hours="24" />                                     //设置缓存有效期
  <flushOnExecute statement="updateUser" />          //执行特定statment是清空缓存
  <property name="size" value="1000" />                  //设置缓存大小
 </cacheModel>
 
 <resultMap id="userResult" class="user">                //resultMap结果映射
  <result property="id" column="id" />
  <result property="name" column="name" />
  <result property="sex" column="sex" />
 </resultMap>
 
 <!-- Statement配置 -->
 <select id="getUser" resultMap="userResult" parameterClass="string">   //parameterClass参数类
    <![CDATA[
        select
             name,
             sex
        from
             t_user
        where
             name=#name#
    ]]>
 </select>
 
 <select id="getUserById" resultClass="user" parameterClass="Integer">  //resultClass结果类
  <![CDATA[
        select
             name,
             sex
        from
             t_user
        where
             id=#id#
     ]]>
 </select>
 
 <insert id="insertUser" parameterClass="user">
        <![CDATA[
        INSERT INTO t_user (
         name,
         sex
        ) values (
   #name#,
   #sex#
        )
    ]]>
 </insert>
 <delete id="deleteUser" parameterClass="Integer">
     <![CDATA[
     delete from t_user
     WHERE id=#id#
     ]]>
 </delete>
 <update id="updateUser" parameterClass="user">
     <![CDATA[
     update t_user
      set
       name=#name#,
       sex=#sex#
     WHERE id=#id#
     ]]>
 </update>
 
</sqlMap>

测试类
 public void testIbatisSqlMap() throws SQLException{
  String resource="sqlmap-config.xml";
  try {
   Reader reader=Resources.getResourceAsReader(resource);
   SqlMapClient sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);    //SqlMapClient核心类
   try{
    sqlMap.startTransaction();

//    User user=new User();
//    user.setId(new Integer(1));
//    user.setName("Samantha");
//    user.setSex(new Integer(11));
//    sqlMap.insert("insertUser",user);

    Integer key=new Integer(2);
    User user1=(User)sqlMap.queryForObject("getUserById",key);
   
    sqlMap.commitTransaction();
    System.out.println(user1.getName());
   } catch (SQLException e) {
    e.printStackTrace();
   }finally{
    sqlMap.endTransaction();
   }
  } catch (IOException e) {
   e.printStackTrace();
  }
}

 

Ibatis高级特性:

1.数据关联:(一对多关联)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://toolkit.alibaba-inc.com/dtd/ibatis/sql-map-2.dtd">
<sqlMap namespace="User">
 <typeAlias alias="user" type="com.ibatis.ao.User" />
 <typeAlias alias="address" type="com.ibatis.ao.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="User.getUsers" parameterClass="java.lang.String"
  resultMap="get-user-result">
 <![CDATA[
  select
   id,
   name,
   sex
  from t_user
  where id = #id#
 ]]>
 </select>
 
 <select id="User.getAddressByUserId" parameterClass="int"
  resultClass="address">
 <![CDATA[
  select
   address,
   zipcode
  from t_address
  where user_id = #userid#
 ]]>
 </select>
</sqlMap>

对应代码:

public void testIbatisSqlMap() throws SQLException, IOException {
  String resource = "sqlmap-config.xml";
  Reader reader = Resources.getResourceAsReader(resource);
  SqlMapClient sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);
  // sqlMap系统初始化完毕
  List userList = sqlMap.queryForList("User.getUsers", "2");
  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(new String(addr.getAddress()));
   }
  }
 }

这种对应在大数据量的情况下会产生性能问题

如果是一对一关系:

<resultMap >
  <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 parameterClass="string"
  resultMap="get-user-result">
  <![CDATA[
    select
       *
    from t_user,t_address
    where t_user.id=t_address.user_id
  ]]>
</select>

 

2.延迟加载:当真正访问对象时才执行SQL语句,提高了系统性能。

3.动态映射

<dynamic prepend="WHERE">
  <isNotEmpty prepend="AND" property="name">
    (name like #name#)
  </isNotEmpty>
  <isNotEmpty prepend="AND" property="address">
    (address like #address#)
  </isNotEmpty>
</dynamic>

一元判定:is(Not)PropertyAvailable,is(Not)Null,is(Not)Empty

二元判定:is(Not)Equal,isGreatThan,isGreatEqual,isLessThan,isLessEqual

4.事务管理

传统JDBC事务:

try{

  sqlMap.startTransaction();

  ...

  sqlMap.commitTransaction();

}finally{

  sqlMap.endTransaction();

}

JTA事务管理:提供了跨数据库事务管理能力

外部事务管理:<transactionManager type="EXTERNAL">

UserTransaction tx=new InitialContext().lookup("...");

...

tx.commit();

5.Cache

readonly、serialize(全局数据缓存)特性

Type:MEMORY、LRU、FIFO、OSCACHE

SoftReference、WeakReference、PhantomReference

<cacheModel type="MEMORY">
  <flushInterval hours="24"/>
  <flushOnExecute statement="updateUser"/>
  <property value="WEAK" />
</cacheModel>

 

Ibatis in Spring:

接口:

public interface IUserDAO {
 public void insertUser(User user);
}

实现类:

public class UserDao extends SqlMapClientDaoSupport implements IUserDAO{

 public void insertUser(User user){
  getSqlMapClientTemplate().update("insertUser",user);
 }
}

模型类配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://toolkit.alibaba-inc.com/dtd/ibatis/sql-map-2.dtd">
<sqlMap namespace="User">
 <typeAlias alias="user" type="com.ibatis.ao.User" />
 <insert id="insertUser" parameterClass="user">
  INSERT INTO users(username,password) VALUES (#username#,#password#)
 </insert>
</sqlMap>

拦截器:

public class SqlInterceptor extends SqlMapClientDaoSupport implements MethodInterceptor{

 public Object invoke(MethodInvocation invocation) throws Throwable {

   //可以doSomething
  Object returnValue=null;

  //可以doSomething
  returnValue=invocation.proceed();
  return returnValue;
 }
}
ibatis配置文件:

<?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>
 <sqlMap resource="com/ibatis/ao/User.xml" />
</sqlMapConfig>

Spring配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
 <description>Spring Ibatis</description>
 <bean id="dataSource"

        class ="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> //DBCP连接数据库
  <property name="driverClassName">
   <value>com.p6spy.engine.spy.P6SpyDriver</value>            //利用P6Spy来显示执行的SQL语句

 </property>
<property name="url">
   <value>jdbc:mysql://localhost:3306/mysql</value>
  </property>
  <property name="username">
   <value>root</value>
  </property>
  <property name="password">
   <value>password</value>
  </property> 
 </bean>
 
 <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
  <property name="configLocation">
   <value>sqlmap-config.xml</value>
  </property>  
 </bean>
 
 <bean id="sqlInterceptor" class="com.taobao.ibatis.dao.SqlInterceptor">      //实现一个拦截器
  <property name="sqlMapClient">
   <ref local="sqlMapClient"/>
  </property>
  <property name="dataSource">
   <ref local="dataSource"/>
  </property>
 </bean>
 
 <bean id="myPointcutAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">      //设置切点
  <property name="advice">
   <ref local="sqlInterceptor"/>
  </property>
  <property name="patterns">
   <list>
    <value>.*insert.*</value>
   </list>
  </property>
 </bean>
 
 <bean id="userDAO" class="com.taobao.ibatis.dao.UserDao"> 
  <property name="dataSource">
   <ref local="dataSource"/>
  </property>
  <property name="sqlMapClient">
   <ref local="sqlMapClient"/>
  </property>
 </bean>
 
 <bean id="userDAOProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> //设置代理类
  <property name="proxyInterfaces">
   <value>com.ibatis.ao.IUserDAO</value>
  </property>
  <property name="target">
   <ref local="userDAO"/>
  </property>
  <property name="interceptorNames">
   <value>myPointcutAdvisor</value>
  </property>
 </bean>
</beans>

附:p6spy.properties配置文件

module.log=com.p6spy.engine.logging.P6LogFactory
realdriver=com.mysql.jdbc.Driver
deregisterdrivers=true
executionthreshold=
outagedetection=false
outagedetectioninterval=
filter=false
include     =
exclude     =
sqlexpression =
autoflush   = true
dateformat=
includecategories=
excludecategories=info,debug,result,batch
stringmatcher=
stacktrace=false
stacktraceclass=
reloadproperties=false
reloadpropertiesinterval=60
useprefix=false
appender=com.p6spy.engine.logging.appender.StdoutLogger
append=true
log4j.appender.STDOUT=org.apache.log4j.ConsoleAppender
log4j.appender.STDOUT.layout=org.apache.log4j.SimpleLayout
log4j.appender.STDOUT.layout.ConversionPattern=p6spy
log4j.logger.p6spy=DEBUG,STDOUT

 

测试类:

public void testIbatisSqlMap(){
  ApplicationContext ctx=new FileSystemXmlApplicationContext("ibatiscontext.xml");
  IUserDAO userdao=(IUserDAO)ctx.getBean("userDAOProxy");
  User user=new User();
  user.setUsername("Samantha");
  user.setPassword("miss");
  userdao.insertUser(user);
 }

原创粉丝点击