Tip:mapper.xml中sql语句不允许出现分号!
1、ibatis中#和$符号的区别
$中间的变量就是直接替换成值的。
#会根据变量的类型来进行替换。
使用场景:
(1)对于变量部分, 应当使用#, 这样可以有效的防止sql注入,具体执行时,# 都是用到了prepareStement,这样对效率也有一定的提升
#方式一般用于传入插入/更新的值或查询/删除的where条件
(2) $只是简单的字符拼接而已,对于非变量部分, 那只能使用$, 实际上, 在很多场合,$也是有很多实际意义的
$方式一般用于传入数据库对象.例如传入表名.
例如:
select * from $tableName$ 对于不同的表执行统一的查询
update $tableName$ set name = #name# 每个实体一张表,改变不用实体的状态
特别说明, $只是字符串拼接,所以要特别小心sql注入问题。
(3)能同时用#和$的时候,最好用#
2、ibatis何时使用CDATA?
在xml元素中,"<"和"&"是非法的,"<"会产生错误,因为解析器会把该字符解释为新元素的开始."&"也会产生错误,因为解析器会把该字符解释为字符实体的开始。
所以这时候会用"<![CDATA[ ]]>" 括起来。
3、批量插入,iterate标签。其中 COMPUTE_MSEL 是FUNCTION
<insert id="batchInsert" parameterClass="java.util.List"> insert all <iterate conjunction=" "> into MONITOR_T_STA_TRACEDAILY (TXNTRACENUMBER, TXNCODE, TXNREQUESTCHANNELID, TXNBOCBANKREQUESTTIME, TXNBOCBANKREQUESTDATE, TXNBOCBANKRESPONSETIME, TXNBOCBANKRESPONSEDATE, TXNRETURNCODE, TXNRETURNMESSAGE, RESPONSESECONDS, CREATETIME) values <![CDATA[ (#recordList[].txntracenumber#, #recordList[].txncode#, #recordList[].txnrequestchannelid#, #recordList[].txnbocbankrequesttime#, #recordList[].txnbocbankrequestdate#, #recordList[].txnbocbankresponsetime#, #recordList[].txnbocbankresponsedate#, #recordList[].txnreturncode#, #recordList[].txnreturnmessage#, COMPUTE_MSEL( #recordList[].txnbocbankrequestdate#, #recordList[].txnbocbankrequesttime#, #recordList[].txnbocbankresponsedate#, #recordList[].txnbocbankresponsetime#), sysdate) ]]> </iterate> select * from dual </insert>
4、批量插入时,当插入数据量太大时,会报 Cause: java.sql.SQLException: ORA-01745: 无效的主机/绑定变量名
这时候采用,分批插入的方式,如下:
public Long insertBatch(List<StaTraceDaily> list){ //每批次插入数量 int batchCount = 1000; //游标 int index = 0; //批次 int batchNum = 1; try { for(;;){ if(index+batchCount>=list.size()){ //一次可全部插入 batchInsert(list.subList(index,list.size())); System.out.println("第"+batchNum+"批:插入"+(list.size()-index)+"条"); break; }else { //需要多次插入 List<StaTraceDaily> staTraceDailyList = list.subList(index, index + batchCount); batchInsert(staTraceDailyList); index = index+batchCount; System.out.println("第"+batchNum+"批:插入"+batchCount+"条"); } batchNum++; } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("over~,总共插入"+list.size()+"条,插入了"+batchNum+"批"); return null; }
5、事务
Tip:
事务不能嵌套。在调用 commit()或 rollback()之前,从同一线程多次调用.startTransaction,将引起抛出异常。
对于每个 SqlMap 实例,每个线程最多只能打开一个事务。
例:
UserDao.insertUser (user); // Starts transaction user.setName("wh"); UserDao.updateUser (user); // Starts a new transaction
因为没有显式地启动事务,iBatis会认为这是两次事务,分别从连接池中取两次Connection。
try { daoManager.startTransaction(); UserDao.insertUser (user); user.setName("wh"); UserDao.updateUser(user); otherDao.doSomething(other); ... daoManager.commitTransaction(); } finally { daoManager.endTransaction(); }
这样就保持了原子性,整体为一个事务,要么全部执行成功,否则回滚。