insert into users(USERNAME,PASSWORD,AGE,MOBILE,EMAIL)

values(#userName:VARCHAR#,#password:VARCHAR#,#age:INT#,#mobile:VARCHAR#,#email:VARCHAR#)

select LAST_INSERT_ID()

向数据库中插入一条记录同时获取了其生成的主键值,主键字段是userId,类型是int这都很好理解。而在程序中,我们只需这么来操作:

ParameterMap parameterMap = new ParameterMap("userName", "sarin",

"password", "123", "age", "23", "mobile", "1", "email", "@");

Object obj = sqlMap.insert("User.addUser", parameterMap);

System.out.println(obj);

打印出的就是主键的值了,这个示例不但演示了iBatis的插入操作,也演示了插入操作同时获取主键值的方法,当然在Oracle中使用序列就行了,SQL Server是使用SCOPE_IDENTITY()函数,这参考一下数据库文档即可。

上面我们在执行更新操作时传递的参数是我们写好的ParameterMap类型,即:

package ibatis.util;

import java.util.HashMap;

public class ParameterMap extends HashMap {

private static final long serialVersionUID = 1L;

public ParameterMap(Object... parameters) {

for (int i = 0; i < parameters.length - 1; i += 2) {

super.put(parameters[i], parameters[i + 1]);

}

}

}

这是内联参数映射的一种,当然我们也可以使用Javabean作为参数传递的对象,来看一个示例:

User user = new User(null, "sarin", "123", "15940900000", "@", 23);

Object obj = sqlMap.insert("User.addUser", user);

System.out.println(obj);

这样使用的前提是在User类中重载一个构造方法来传递属性的值,当然默认的构造方法也要有(当你调用了queryForObject()方法时)。另外一种是外部参数映射,我们定义一个parameterMap来测试这种情况:

自动生成的主键userId这里我们就不用写了,然后定义插入语句的映射:

insert into

users(USERNAME,PASSWORD,AGE,MOBILE,EMAIL)

values(?,?,?,?,?)

select LAST_INSERT_ID()

最后在程序中,则和上面内联参数没有什么不同,除了映射的语句名称:

User user = new User(null, "sarin", "123", "15940900000", "@", 23);

Object obj = sqlMap.insert("User.addUserUseParameterMap", user);

System.out.println(obj);

更新操作的第二种是update,SqlMap API中更新操作的方法签名是int update(String id, Object parameterObject) throws SQLException,参数的含义都已经非常清楚了,就是映射的语句名称和参数,而返回值是int型的。在JDBC规范中我们知道更新操作返回的是影响的结果行数,其实insert也是,只不过SqlMap给我们了新的选择。

要注意的一点是iBatis允许在一条SQL语句中更新一条或多条记录,而其他面向对象的工具是只允许修改一条记录(比如Hibernate),但Hibernate针对批量操作也做了处理。

说到批量操作,就会有并发的问题,那么事务机制很自然就要想到了,这里简单介绍一下iBatis处理批量操作的方法,后面会有详细介绍iBatis的事务。这里给出一个处理并发的小技巧,就是在高并发的数据表中加一个时间戳字段或者是版本字段控制,每次更新操作都修改这个字段,就能一定程度上控制数据完整性。

由于iBatis是SQL映射工具,那么就不需要像使用Hibernate那样考虑对象间的关系,在程序中做好处理就行了。先看下面这个示例:购物车订单,这是很经典的示例,我们需要建立两个类(订单和订单项),两个SQL映射文件和一个测试类。数据库表结构如下:

这是订单表,简单做示例,就订单名称和生成订单的时间两项即可。

这是订单项表,字段见名知意,这里就不多解释了。下面来看看实体类的设计:

package ibatis.model;

import java.util.Date;

import java.util.List;

public class Order implements java.io.Serializable {

private Integer orderId;

private String orderName;

private java.util.Date generateTime;

private List orderItems;

public Order() {

}

public Order(Integer orderId, String orderName, Date generateTime,

List orderItems) {

super();

this.orderId = orderId;

this.orderName = orderName;

this.generateTime = generateTime;

this.orderItems = orderItems;

}

// 省略getter和setter方法

@Override

public String toString() {

return "Order [generateTime=" + generateTime + ", orderId=" + orderId+ ", orderItems=" + orderItems + ", orderName=" + orderName+ "]";

}

}

下面是订单项的实体类,也很简单:

package ibatis.model;

public class OrderItem implements java.io.Serializable {

private Integer oderItemId;

private String itemName;

private int quantity;

private float price;

private Integer orderId;

public OrderItem() {

}

public OrderItem(Integer oderItemId, String itemName, int quantity,

float price, Integer orderId) {

super();

this.oderItemId = oderItemId;

this.itemName = itemName;

this.quantity = quantity;

this.price = price;

this.orderId = orderId;

}

// 省略getter和setter方法

@Override

public String toString() {

return "OrderItem [itemName=" + itemName + ", oderItemId=" + oderItemId+ ", orderId=" + orderId + ", price=" + price + ", quantity="

+ quantity + "]";

}

}

虽然iBatis是SQL映射,但是实体类中我们使用对象类型而不是基本数据类型还是有很多好处的,比如直接和null判断。下面我们来看SQL映射文件,其中使用了简单的动态SQL,这个后面会详细来说明。

insert into

orders(orderName,generateTime)

values

(#orderName:VARCHAR#,now())

select LAST_INSERT_ID()

update

orders

set

orderName=#orderName:VARCHAR#

where

orderId=#orderId:INT#

delete from

orderitems

where

orderId=#orderId:INT#

分析一下这个配置,首先定义了Order类型,在文件中可以直接使用。然后就是SQL语句了,有添加,更新和删除操作,其中删除是删除所有的订单项,插入操作后返回自动生成的主键,这个在前面已经说明了,很好理解。那么订单项的配置文件就更简单了:

insert into

orderitems(itemName,quantity,price,orderId)

values(#itemName:VARCHAR#,#quantity:INT#,#price:FLOAT#,#orderId:INT#)

只有一个添加语句做示例。最后不要忘了在SqlMapConfig中引入这两个配置文件,下面来看看测试类:

package ibatis;

// 省略包引入语句

public class OrderDemo {

private static String config = "ibatis/SqlMapConfig.xml";

private static Reader reader;

private static SqlMapClient sqlMap;

static {

try {

reader = Resources.getResourceAsReader(config);

} catch (IOException e) {

e.printStackTrace();

}

sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);

}

public static void main(String[] args) throws SQLException{

OrderItem item1 = new OrderItem(null, "IBM THINKPAD T410", 1, 10000, null);

OrderItem item2 = new OrderItem(null, "HP 6930P", 1, 7000, null);

OrderItem item3 = new OrderItem(null, "APPLE MC024", 1, 16000, null);

// 创建OrderItem对象集合,放入三个购物项

List orderItems = new ArrayList();

orderItems.add(item1);

orderItems.add(item2);

orderItems.add(item3);

Order order = new Order(null, "Sarin's Order", null, orderItems);

saveOrder(sqlMap, order);

}

public static void saveOrder(SqlMapClient sqlMap, Order order)

throws SQLException {

// 判断是插入订单还是更新

if (null == order.getOrderId()) {

sqlMap.insert("Order.insert", order);

} else {

sqlMap.update("Order.update", order);

}

// 清除订单原有信息

sqlMap.delete("Order.deleteDetails", order);

// 插入订单项目

for (int i = 0; i < order.getOrderItems().size(); i++) {

OrderItem oi = order.getOrderItems().get(i);

oi.setOrderId(order.getOrderId());

sqlMap.insert("OrderItem.insert", oi);

}

}

}

代码能为我们完成任务,但是可以看出,这里没有任何的事务隔离,如果循环插入时发生了异常,那么数据完整性将遭到破坏。这是因为此时的事务是在每条语句执行时提交的,这也会影响程序的执行性能。做如下测试,修改main函数为:

public static void main(String[] args) throws SQLException {

long start = System.currentTimeMillis();

// 中间执行代码

long end = System.currentTimeMillis();

System.out.println(end - start);

}

一次测试时间是494,而如果:

public static void main(String[] args) throws SQLException,IOException {

long start = System.currentTimeMillis();

String config = "ibatis/SqlMapConfig.xml";

Reader reader= Resources.getResourceAsReader(config);

SqlMapClient sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);

// 中间执行代码

long end = System.currentTimeMillis();

System.out.println(end - start);

}

执行时间可达到874,所以性能是很低的。下面我们来看看批量更新操作,将saveOrder()方法做如下修改:

public static void saveOrder(SqlMapClient sqlMap, Order order)

throws SQLException {

// 开启事务

sqlMap.startTransaction();

try {

// 判断是插入订单还是更新

if (null == order.getOrderId()) {

sqlMap.insert("Order.insert", order);

} else {

sqlMap.update("Order.update", order);

}

// 开始批量操作

sqlMap.startBatch();

// 清除订单原有信息

sqlMap.delete("Order.deleteDetails", order);

// 插入订单项目

for (int i = 0; i < order.getOrderItems().size(); i++) {

OrderItem oi = order.getOrderItems().get(i);

oi.setOrderId(order.getOrderId());

sqlMap.insert("OrderItem.insert", oi);

}

sqlMap.executeBatch();

sqlMap.commitTransaction();

} finally {

sqlMap.endTransaction();

}

}

测试出的运行时间是432,确实效率提高了,因为数据量小,不是很明显。这里要注意批量操作的开始地方,因为后面的OrderItem使用到了Order的主键,而这个主键是数据库自动生成的,那么我们必须获取到这个主键才能执行批量那个操作。而在executeBatch()执行时才会执行SQL操作,如果开始批量的位置不对,则不能获取到创建的主键的值,那么后面的操作也不能被执行了。

最后就是存储过程了,这里给出一个简单的示例:在存储过程中删除订单详细项,一个比较奇怪的地方就是iBatis调用mysql的存储过程要使用insert()方法,这里并不知道其原因。首先我们定义一个存储过程:

在SQL配置中,我们定义一个存储过程和映射参数类型:

call delete_orderitems_by_orderid(?)

程序中,使用insert()方法调用存储过程,比如:

Map m = new HashMap();

m.put("orderId", 3);

sqlMap.queryForObject("Order.deleteOrderitemsByOrderId", m);

除了存储过程,还有函数,我们也来看个示例:

CREATE DEFINER = `root`@`localhost` FUNCTION `max_in_example`(`a` int,`b` int)

RETURNS int(10)

BEGIN

if(a > b) then

return a;

else

return b;

end if;

END;

这是MySQL的一个函数定义,在SQL映射文件中,必须使用select来标记,而不是procedure,这个要记住。

select max_in_example(?,?)

程序中,这样写就行了:

Map m = new HashMap(2);

m.put("a", new Integer(7));

m.put("b", new Integer(5));

Integer val = (Integer) sqlMap.queryForObject("User.in_example", m);

System.out.println(val);

打印的结果就是7。至此iBatis的非查询语句就介绍完了。

大小: 41.3 KB

大小: 46.5 KB

大小: 46.4 KB

下载次数: 75

5

1

分享到:

2012-08-26 21:40

浏览 8997

评论

2 楼

sarin

2012-08-27

hellostory 写道

关于ibats更新update的书写方式,个人愚见:

为什么非得要“”才能更新字段呢?有这样一种情况,用户之前在备注字段写了一些信息,现在想把备注字段清空,那就没法实现了。

那是动态SQL的一部分,用于判断字段逻辑而进行最终SQL的动态拼装

1 楼

hellostory

2012-08-27

关于ibats更新update的书写方式,个人愚见:

为什么非得要“”才能更新字段呢?有这样一种情况,用户之前在备注字段写了一些信息,现在想把备注字段清空,那就没法实现了。

mysql执行非查询语句_iBatis执行非查询语句(CRUD,函数和过程)相关推荐

  1. Python|SQL详解之DDL|DML|DQL|DCL|索引|视图、函数和过程|JSON类型|窗口函数|接入MySQL|清屏|正则表达式|executemany|语言基础50课:学习(14)

    文章目录 系列目录 原项目地址 第41课:SQL详解之DDL 建库建表 删除表和修改表 第42课:SQL详解之DML insert操作 delete 操作 update 操作 完整的数据 第43课:S ...

  2. Mysql(一)一条查询语句的执行流程

    MySQL 的内部模块简介 1. Connector:用来支持各种语言和 SQL 的交互,比如 PHP,Python,Java 的JDBC: 2. Management Serveices & ...

  3. 一条mysql查询语句的执行过程

    当我们执行一条MySQL查询语句时,对于客户端而言是一个很简单的过程,但对于服务端来说其内部却会涉及到一些复杂的组件和处理逻辑.了解MySQL语句的内部执行原理,有助于我们更好地去处理一些复杂的SQL ...

  4. MySQL番外篇:一条SQL查询语句是如何执行的?

    在面试的过程中,有的面试官会给出一条简单的SQL查询语句,让简单说一下执行的过程. SELECT * FROM emp where age=30; 以下问MySQL的基本架构图,从中可以看出SQL语句 ...

  5. 讲mysql执行流程书籍_MySQL 基础架构 1. 一条SQL查询语句的执行过程(个人学习笔记)...

    MySQL的逻辑架构图: MySQL 大体分为 "server 层" 和 "存储引擎层" 两部分: Server 层 包括 连接器.查询缓存.分析器.优化器.执 ...

  6. go mysql 查询语句_01 MySQL-初识MySQL-查询语句的执行流程-Go语言中文社区

    MySQL的基础架构 我们通过一条查询语句来看看MySQL是如何执行的,同时通过这条语句的执行,了解MySQL的整体架构体系.mysql> select * from T where ID=1: ...

  7. 【MySQL原理解析】01. 一条SQL查询语句是如何执行的

    这是[MySQL原理解析]的第一篇文章,MySQL我看了很多的书与教程,对其原理有一定的理解,一直想写一系列的文章来把MySQL的原理给讲清楚,一直没有时间写,今天算是个开头吧.万事开头难,咱们先破了 ...

  8. 一文读懂MySQL查询语句的执行过程

    需要从数据库检索某些符合要求的数据,我们很容易写出 Select A B C FROM T WHERE ID = XX  这样的SQL,那么当我们向数据库发送这样一个请求时,数据库到底做了什么? 我们 ...

  9. mysql要将语句反复执行15次_MySQL多表查询疑问

    2019年6月20日,时隔快一个月,时不时想想这个问题,终于发现错在哪里了. 正确的写法应该是:当查询中存在group by子句时,select列表(或是having子句)中只能存在分组函数,或是出现 ...

最新文章

  1. 通过View.post()获取View的宽高
  2. 华章数学译丛目录(2020年7月补缺更新版,共73本)
  3. 最萌办公室采访 | 网易程序员灵魂大拷问(文末有福利)
  4. python怎样在一行中捕获多个异常
  5. c语言程序机试题及答案,C语言程序设计试题及答案解析(二)
  6. js识别用户设备是移动端手机时跳转到手机网站
  7. 交互式编程神器jupyter notebook环境搭建【不需要虚拟环境就能实现python2版本和python3版本自由切换】
  8. 微信内置浏览器直接下载APK的解决方法
  9. Anaconda spyder下载第三方包
  10. 国人走向世界的一个很好的艺术与设计网站
  11. std::adjacent_find 用法
  12. cocos之游戏手柄控制实例
  13. android webview应用,Android WebView简单应用
  14. 深度学习之CNN卷积神经网络详解以及猫狗识别实战
  15. GoKit3(V)学习笔记02_自定义产品数据点
  16. TMS320x2833x的ePWM模块简要介绍
  17. 智慧文旅IOC大数据可视化建设方案
  18. 1.1 DB DBMS DBA DBS简述
  19. v2ex突然打不开了...
  20. 互动性可视化 打通大数据最后一公里

热门文章

  1. 有机创业点子 -- 读后
  2. 动物园(虚函数与多态)
  3. 【LeetCode】427. Construct Quad Tree 建立四叉树
  4. 历史上终身未婚21个名人
  5. 基于社区发现算法对CWE的划分实践
  6. 大前端涉猎之前后端交互总结2:使用PHP进行表单数据上传与更新
  7. macos复制粘贴快捷键 快速_Mac怎么修改复制黏贴快捷键?Mac修改复制黏贴快捷键的方法...
  8. itune备份在哪里_iTune的iPhone备份文件在哪里,以及如何从中获取真实文件?
  9. 《计算机网络 自顶向下方法》读书笔记 第7章 无线网络和移动网络
  10. 【Filecoin周报】58:校准网络启动,有奖测试进入倒计时