`
wsqian
  • 浏览: 40363 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

sping中ibatis数据库操作

阅读更多
getSqlMapClientTemplate.insert() 返回的是新插入数据的主键值
getSqlMapClientTemplate.update() 返回的是更新的记录
public int deleteEntity(Map key)throws DataAccessException{
    return getSqlMapClientTemplate().delete(getDeleteStatement(), key);
  }

  public Entity retrieveEntity(Map key)throws DataAccessException{
    return ((Entity)getSqlMapClientTemplate().queryForObject(getSelectStatement(), key));
  }

  public int updateEntity(Entity entity)throws DataAccessException{
    return getSqlMapClientTemplate().update(getUpdateStatement(), entity);
  }
============================================================================================================================================
从4个层面分析这部分实现:

iBatis的基本实现
基于事务的iBatis的基本实现
基于事务的Spring+iBatis实现
基于回调方式的Spring+iBatis实现


1.iBatis的基本实现
iBatis通过SqlMapClient提供了一组方法用于批处理实现:

startBatch() 开始批处理
executeBatch() 执行批处理

代码如下:
Java代码 
public void create(List<Reply> replyList) {  
 
    try {  
        // 开始批处理  
        sqlMapClient.startBatch();  
 
        for (Reply reply: replyList) {  
            // 插入操作  
            sqlMapClient.insert("Reply.create", reply);  
        }  
        // 执行批处理  
        sqlMapClient.executeBatch();  
 
    } catch (Exception e) {  
        e.printStackTrace();  
    }  


public void create(List<Reply> replyList) {

try {
// 开始批处理
sqlMapClient.startBatch();

for (Reply reply: replyList) {
// 插入操作
sqlMapClient.insert("Reply.create", reply);
}
// 执行批处理
sqlMapClient.executeBatch();

} catch (Exception e) {
e.printStackTrace();
}
}

这是基于iBatis的最基本实现,如果你一步一步debug,你会发现:其实,数据库已经执行了插入操作!
因此,除了这两个核心方法外,你还需要开启事务支持。否则,上述代码只不过是个空架子!

2.基于事务的iBatis的基本实现
事务处理:

startTransaction() 开始事务
commitTransaction() 提交事务
endTransaction() 结束事务


我们以insert操作为例,把它们结合到一起:
Java代码 
public void create(List<Reply> replyList) {  
 
    try {  
        // 开始事务  
        sqlMapClient.startTransaction();  
        // 开始批处理  
        sqlMapClient.startBatch();  
 
        for (Reply reply: replyList) {  
            // 插入操作  
            sqlMapClient.insert("Reply.create", reply);  
        }  
        // 执行批处理  
        sqlMapClient.executeBatch();  
 
        // 提交事务  
        sqlMapClient.commitTransaction();  
 
    } catch (Exception e) {  
        e.printStackTrace();  
    } finally {    
             try {  
            // 结束事务  
            sqlMapClient.endTransaction();  
                } catch (SQLException e) {  
                         e.printStackTrace();  
                     }  
    }    


public void create(List<Reply> replyList) {

try {
// 开始事务
sqlMapClient.startTransaction();
// 开始批处理
sqlMapClient.startBatch();

for (Reply reply: replyList) {
// 插入操作
sqlMapClient.insert("Reply.create", reply);
}
// 执行批处理
sqlMapClient.executeBatch();

// 提交事务
sqlMapClient.commitTransaction();

} catch (Exception e) {
e.printStackTrace();
} finally { 
try {
// 结束事务
sqlMapClient.endTransaction();
            } catch (SQLException e) {
                e.printStackTrace();
            }

}

replyList是一个List,要把这个List插入到数据库,就需要经过这三个步骤:

开始批处理 startBatch()
插入      insert()
执行批处理 executeBatch()

如果要在Spring+iBatis中进行批处理实现,需要注意使用同一个sqlMapClient!同时,将提交事务的工作交给Spring统一处理!

3.基于事务的Spring+iBatis实现
Java代码 
public void create(List<Reply> replyList) {  
    if (!CollectionUtils.isEmpty(replyList)) {  
        // 注意使用同一个SqlMapClient会话  
        SqlMapClient sqlMapClient = sqlMapClientTemplate.getSqlMapClient();  
 
        try {  
            // 开始事务  
            sqlMapClient.startTransaction();  
            // 开始批处理  
            sqlMapClient.startBatch();  
            for (Reply reply : replyList) {  
                // 插入操作  
                sqlMapClient.insert("Reply.create", reply);  
            }  
 
            // 执行批处理  
            sqlMapClient.executeBatch();  
            // 提交事务 交给Spring统一控制  
            // sqlMapClient.commitTransaction();  
 
        } catch (Exception e) {  
            e.printStackTrace();  
        } finally {    
                 try {  
                // 结束事务  
                sqlMapClient.endTransaction();  
                    } catch (SQLException e) {  
                             e.printStackTrace();  
                         }  
        }    
    }  


public void create(List<Reply> replyList) {
if (!CollectionUtils.isEmpty(replyList)) {
// 注意使用同一个SqlMapClient会话
SqlMapClient sqlMapClient = sqlMapClientTemplate.getSqlMapClient();

try {
// 开始事务
sqlMapClient.startTransaction();
// 开始批处理
sqlMapClient.startBatch();
for (Reply reply : replyList) {
// 插入操作
sqlMapClient.insert("Reply.create", reply);
}

// 执行批处理
sqlMapClient.executeBatch();
// 提交事务 交给Spring统一控制
// sqlMapClient.commitTransaction();

} catch (Exception e) {
e.printStackTrace();
} finally { 
try {
// 结束事务
sqlMapClient.endTransaction();
            } catch (SQLException e) {
                e.printStackTrace();
            }

}
}

注意使用同一个sqlMapClient:
SqlMapClient sqlMapClient = sqlMapClientTemplate.getSqlMapClient();
如果直接sqlMapClientTemplate执行insert()方法,将会造成异常!

想想,还有什么问题?其实问题很明显,虽然解决了批处理实现的问题,却造成了事务代码入侵的新问题。 这么做,有点恶心!
除此之外,异常的处理也很恶心,不能够简单的包装为 DataAccessException 就无法被Spring当作统一的数据库操作异常做处理。


4.基于回调方式的Spring+iBatis实现
如果观察过Spring的源代码,你一定知道,Spring为了保持事务统一控制,在实现ORM框架时通常都采用了回调模式,从而避免了事务代码入侵的可能!
修改后的代码如下:
Java代码 
@SuppressWarnings("unchecked")  
public void create(final List<Reply> replyList) {  
    // 执行回调  
    sqlMapClientTemplate.execute(new SqlMapClientCallback() {  
        // 实现回调接口  
        public Object doInSqlMapClient(SqlMapExecutor executor)  
                throws SQLException {  
            // 开始批处理  
            executor.startBatch();  
            for (Reply reply : replyList) {  
                // 插入操作  
                executor.insert("Reply.create", reply);  
 
            }  
            // 执行批处理  
            executor.executeBatch();  
 
            return null;  
 
        }  
    });  
 


@SuppressWarnings("unchecked")
public void create(final List<Reply> replyList) {
// 执行回调
sqlMapClientTemplate.execute(new SqlMapClientCallback() {
// 实现回调接口
public Object doInSqlMapClient(SqlMapExecutor executor)
throws SQLException {
// 开始批处理
executor.startBatch();
for (Reply reply : replyList) {
// 插入操作
executor.insert("Reply.create", reply);

}
// 执行批处理
executor.executeBatch();

return null;

}
});

}

注意,待遍历的参数replyList需要加入final标识!即,待遍历对象不能修改!

引用
public void create(final List<Reply> replyList)

============================================================================================================================================
ibatis中iterate的用法

--------------------------------------------------------------------------------
2008-10-27 13:16:15 标签:ibatis iterate   [推送到技术圈]版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://sunfish.blog.51cto.com/417500/108315
PersonDaoImp如下: /**
     * 删除性别为man,年龄为 11,12 的Person记录
     */
  public int deletePerson(Map<String, Object> map) {
        
         List<Person> personList=new ArrayList<Person>();

         Person p1=new Person(11);
         person p2=new Person(12);
         personList.add(p1);
         personList.add(p2);

         map.put("personList", personList);

         map.put("sex",'man');
         return getSqlMapClientTemplate().delete(
                                 "person.deletePerson", map);
     }person.xml如下:
<!-- 删除相应的person记录 -->
  <delete id="deletePerson" parameterClass="map">

     delete from 表名 where      sex=#sex#      
        <iterate prepend="and" property="personList" open="("
          close=")" conjunction="or">
          age=$personList[].age$
        </iterate>
      
  </delete>输出sql如下:
delete from 表名 where sex='man' and (age =11 or age=12)

当然你也可以这么写:
person.xml如下:
<!-- 删除相应的person记录 -->
  <delete id="deletePerson" parameterClass="map">

     delete from 表名 where      sex=#sex#     and age in
        <iterate property="personList" open="("
          close=")" conjunction=",">
          $personList[].age$
        </iterate>
      
  </delete>输出sql如下:
delete from 表名 where sex='man' and age in (11 ,12)

最后Person代码大致如下:
public class Person{
  public Person(int age){
      this.age=age;
}
  /**
     * 年龄
     */
  private int age;
  /**
     * 性别
     */
  private String sex;

   //get/set方法略
   ...
}//end of Person


============================================================================================================================================
batis中sql in语句的配置?
ibatis中如何配置in语句,需要迭代,不能直接用string的写法


<select id="sql_test" parameterclass="myPramBean" resultclass="myResult">
select *from tablewhere name in
<iterate property="ids" conjunction="," close=")" open="(" />
#value[]#
</iterate>
and code=#code#
</select>
myPramBean
{
private String code;
private List ids;
...
}

============================================================================================================================================
                          在iBATIS中正确的使用$和#

们在使用iBATIS时会经常用到#这个符号。

比如:


sql 代码
select * from member where id =#id# 
然后,我们会在程序中给id这个变量传递一个值,iBATIS会自动将#id#转成我们传递的内容。

但是我最近碰到一个奇怪的问题。我在批量删除或修改的时候,居然SQL失效了。

SQL如下:

sql 代码
update user set flag=#flag# where id in (#id#)  
  
delete from user where id in (#id#) 
传递的id为1,2,3。但是数据却没有任何的修改。

后来查找了半天,原来原因就是这个#的问题。因为iBATIS默认会把“#”中间的变量作为字符串来处理。这样,就会出现这样的SQL


sql 代码
update user set flag='1' where id in ('1,2,3')  
  
delete from user where id in ('1,2,3') 
这样的SQL数据库当然是不会执行的。那我们只有绕开iBATIS了吗?

其实不用,iBATIS其实还提供了另外一种方式,那就是使用$来传递值。你使用$将你的变量括起来,iBATIS不会给这个变量做任何的处理,直接生成你要的SQL

sql 代码

update user set flag=$flag$ where id in ($id$)  
  
update user set flag=1  where id in (1,2,3)  
  
delete from user where id in ($id$)  
  
delete from user where id in (1,2,3) 

还可以用ibatis的iterate解决:
SQL:

<select id="test" parameterClass="java.util.List" resultClass="test.Roadline">   
    select * from SYS_ROAD_LINE_INFO where ROAD_LINE_NO in    
    <iterate open="(" close=")" conjunction=",">   
        #value[]#   
    </iterate>   
</select> 
<select id="test" parameterClass="java.util.List" resultClass="test.Roadline"> select * from SYS_ROAD_LINE_INFO where ROAD_LINE_NO in <iterate open="(" close=")" conjunction=","> #value[]# </iterate></select>java: List list = new ArrayList();   
list.add("aaa");   
list.add("bbb");   
               
List rsList = sqlMap.queryForList("roadline.test", list); 
List list = new ArrayList();list.add("aaa");list.add("bbb"); List rsList = sqlMap.queryForList("roadline.test", list);
生成的sql:

select * from SYS_ROAD_LINE_INFO where ROAD_LINE_NO in (?,?) 
$中间的变量就是直接替换成值的
#会根据变量的类型来进行替换
比如articleTitle的类型是string, 值是"标题"的时候
$articleTitle$ = 标题
#articleTitle# = '标题'

如果一个字段的名字不规范带有#,那么在<select ...> select name# from reader where id=#id#...</select>语句中会报错,我看过有人问过这个问题,说是name####但是还是不能解决无法对带#的字段的查询。 解决办法肯定是有的。比如,你可以把这个字段当做一个参数来传递给ibatis。然后用$$把这个变量括起来。


分享到:
评论
1 楼 zuishengmengsi1990 2012-03-21  
我的SSI中就是不能插入数据呢,,是不是事物的问题啊,怎么办呢。。

相关推荐

Global site tag (gtag.js) - Google Analytics