mybatis

mybatis



1.如何批量插入数据

SQL层面

先复习一下单条/批量插入数据的sql语句怎么写:

1. 单条插入数据的写法:

INSERT INTO [表名]

([列名],[列名])

VALUES

([列值],[列值]))

2.一次性批量插入数据的sql语句的写法:

INSERT INTO [表名]

([列名],[列名])

VALUES

([列值],[列值])),

([列值],[列值])),

([列值],[列值]));

批量的好处:可以避免程序和数据库建立多次连接,从而增加服务器负荷。

MyBatis层面如何完成批量插入

MyBatis批量插入数据到数据库有两种方式:xml文件,注解,这里使用MySQL。

方法一:xml配置

最基础的是用mapping.xml配置的方式,包括以下两种具体方式:

1. mapping.xml中insert语句可以写成单条插入,在调用方循环1000次

<!-- 在外部for循环调用1000次 -->

<insert id="insert" parameterType="sdc.mybatis.test.Student">

insert into student (id, name, sex,

address, telephone, t_id

)

values (#{id,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR},

#{sex,jdbcType=VARCHAR},

#{address,jdbcType=VARCHAR}, #{telephone,jdbcType=VARCHAR}, #{tId,jdbcType=INTEGER}

)

</insert>

2. mapping.xml中insert语句写成一次性插入一个1000的list

mapping.xml

<insert id="insertBatch" >

insert into student ( <include refid="Base_Column_List" /> )

values

<foreach collection="list" item="item" index="index" separator=",">

(null,#{item.name},#{item.sex},#{item.address},#{item.telephone},#{item.tId})

</foreach>

</insert>

参数解释:

collection:指定要遍历的集合;

表示传入过来的参数的数据类型。该参数为必选。要做 foreach 的对象,作为入参时,List 对象默认用 list 代替作为键,数组对象有 array 代替作为键,Map 对象没有默认的键;

item:将当前遍历出的元素赋值给指定的变量,然后用#{变量名},就能取出变量的值,也就是当前遍历出的元素;

index:索引,遍历list的时候index就是索引,遍历map的时候index表示的就是map的key,item就是map的值;

separator:每个元素之间的分隔符, select * from Emp where id in(1,2,3)相当于1,2,3之间的","

mapper接口中的使用:

public interface EmpMapper {

public List<Emp> getEmpsByConditionLike(@Param("list")List<Integer> ids);

}

方法二:注解

注解说明:

MyBatis提供用于插入数据的注解有两个:@insert,@InsertProvider,类似还有:@DeleteProvider@UpdateProvider和@SelectProvider;

作用:

用来在实体类的Mapper类里注解保存方法的SQL语句

区别:

@Insert是直接配置SQL语句,而@InsertProvider则是通过SQL工厂类及对应的方法生成SQL语句,这种方法的好处在于,我们可以根据不同的需求生产出不同的SQL,适用性更好。

使用:

@Insert

@Insert("insert into blog(blogId,title,author) values(#blogId,#title,#author)")

public boolean saveBlog(Blog blog);

@InsertProvider

在mapper接口中的方法上使用@InsertProvider注解:

@InsertProvider(type=ActivationProvider.class, method="insertAll")

boolean insertAll(@Param("list") List<String> codeArray);

参数解释:

type为工厂类的类对象,method为对应的工厂类中的方法,方法中的@Param("list")是因为批量插入传入的是一个list,但是Mybatis会将其包装成一个map,其中map的key为"list",value为传入的list。

工厂类ActivationProvider中的方法:

首先要map.get方法得到对应的list;

然后拼接insert语句,要生成的正确的sql语句的格式为:

INSERT INTO User (id, name) VALUES (null, #{list[0].name}), (null, #{list[1].name})[,(null, #{list[i].name})]

其中list[0]代表list中第0个元素

特别注意:

一定注意:注意Mapper到Provider参数类型的变化(List --> Map),Mapper中传入的List会被包裹在一个Map中传给Provider,而key就是在Mapper的@Param注解中指定的名称(默认为list)。在Provider方法中使用List<T> list = (List<T>) map.get(key);即可拿到我们传入的List。

否则会报错:

Caused by: org.apache.ibatis.binding.BindingException: Parameter 'arg0' not found. Available parameters are [1, 0, param1, param2]

xml、注解方式区别:

1.foreach相当语句逐条INSERT语句执行,将出现如下问题:

    a. mapper接口的isnert方法返回值将是最一条INSERT语句的操作成功的记录数目

    (就是0或1),而不是所有INSERT语句的操作成功的总记录数目。

    b. 当其中一条不成功时,不会进行整体回滚。

2.注解方式:当有一条插入不成功时,会整体回滚



2. foreach有什么关键字

<foreach> 元素主要用在构建 in 条件中,它可以在 SQL 语句中迭代一个集合。

<foreach> 元素的属性主要有 item、index、collection、open、separator、close。

item 表示集合中每一个元素进行迭代时的别名。

index 指定一个名字,用于表示在迭代过程中每次迭代到的位置。

open 表示该语句以什么开始。

separator 表示在每次进行迭代之间以什么符号作为分隔符。

close 表示以什么结束。

在使用 <foreach> 元素时,最关键、最容易出错的是collection属性,该属性是必选的,但在不同情况下该属性的值是不一样的,主要有以下3种情况:

如果传入的是单参数且参数类型是一个List,collection属性值为list。

如果传入的是单参数且参数类型是一个array数组,collection的属性值为array。

如果传入的参数是多个,需要把它们封装成一个Map,当然单参数也可以封装成Map。Map的key是参数名,collection属性值是传入的List或array对象在自己封装的Map中的key。

1)添加SQL映射语句

在 com.mybatis 包的 UserMapper.xml 文件中添加如下 SQL 映射语句:

<!--使用foreach元素查询用户信息-->

<select id="selectUserByForeach" resultType="com.po.MyUser" parameterType=

"List">

select * from user where uid in

<foreach item="item" index="index" collection="list"

open="(" separator="," close=")">

# {item}

</foreach>

</select>

2)添加数据操作接口方法

在 com.dao 包的 UserDao 接口中添加如下数据操作接口方法:

public List<MyUser> selectUserByForeach(List<Integer> listId);

3)调用数据操作接口方法

在 com.controller 包的 UserController 类中添加如下程序调用数据操作接口方法。

//使用foreach元素查询用户信息

List<Integer> listId=new ArrayList<Integer>();

listId.add(34);

listId.add(37);

List<MyUser> listByForeach = userDao.selectUserByForeach(listId);

System.out.println ("foreach元素================");

for(MyUser myUser : listByForeach) {

System.out.println(myUser);

}



3.如何自增主键

同一张student表,对于mysql,sql server,oracle中它们都是怎样创建主键的

在mysql中

create table Student(

Student_ID int(6) NOT NULL PRIMARY KEY AUTO_INCREMENT,

Student_Name varchar(10) NOT NULL,

Student_Age int(2) NOT NULL

);

insert into student(student_name,student_age) values('zhangsan',20);

在sql server中

create table Student(

Student_ID int primary key identity(1,1),

Student_Name varchar2(10) NOT NULL,

Student_Age number(2) NOT NULL

);

insert into student(student_name,student_age) values('zhangsan',20);

在oracle中

create table Student(

Student_ID number(6) NOT NULL PRIMARY KEY,

Student_Name varchar2(10) NOT NULL,

Student_Age number(2) NOT NULL

);

oracle如果想设置主键自增长,则需要创建序列

CREATE SEQUENCE student_sequence

INCREMENT BY 1

NOMAXVALUE

NOCYCLE

CACHE 10;

insert into Student values(student_sequence.nextval,'aa',20);

如果使用了触发器的话,就更简单了

create or replace trigger student_trigger

before insert on student

for each row

begin

select student_sequence.nextval into :new.student_id from dual;

end student_trigger;

此时插入的时候触发器会帮你插入id

insert into student(student_name,student_age) values('wangwu',20);

至此,mysql,sql server,oracle中怎样创建表中的自增长主键都已完成。

看一看出oracle的主键自增较mysql和sql sever要复杂些,mysql,sqlserver配置好主键之后,插入时,字段和值一一对应即可,数据库就会完成你想做的,但是在oracle由于多了序列的概念,如果不使用触发器,oracle怎样实现主键自增呢?

<insert id="add" parameterType="Student">

  <selectKey keyProperty="student_id" resultType="int" order="BEFORE">

            select student_sequence.nextval from dual

        </selectKey>

      insert into student(student_id,student_name,student_age) values(#{student_id},#{student_name},#{student_age})

</insert>

或者

<insert id="save" parameterType="com.threeti.to.ZoneTO" >

    <selectKey resultType="java.lang.Long" keyProperty="id" order="AFTER" >

        SELECT SEQ_ZONE.CURRVAL AS id from dual

    </selectKey>

    insert into TBL_ZONE (ID, NAME ) values (SEQ_ZONE.NEXTVAL, #{name,jdbcType=VARCHAR})

</insert>



4.如何使用in

在SQL语法中如果我们想使用in的话直接可以像如下一样使用:

select * from HealthCoupon where useType in ( '4' , '3' )

但是如果在MyBatis中的使用in的话,像如下去做的话,肯定会报错:

Map<String, Object> selectByUserId(@Param("useType") String useType)

<select id="selectByUserId" resultMap="BaseResultMap" parameterType="java.lang.String">

  select * from HealthCoupon where useType in (#{useType,jdbcType=VARCHAR})

</select>

其中useType="2,3";这样的写法,看似很简单,但是MyBatis不支持。但是MyBatis中提供了foreach语句实现IN查询,foreach语法如下:

foreach语句中, collection属性的参数类型可以是:List、数组、map集合

collection: 必须跟mapper.java中@Param标签指定的元素名一样

item: 表示在迭代过程中每一个元素的别名,可以随便起名,但是必须跟元素中的#{}里面的名称一样。

index:表示在迭代过程中每次迭代到的位置(下标)

open:前缀,sql语句中集合都必须用小括号()括起来

close:后缀

separator:分隔符,表示迭代时每个元素之间以什么分隔

正确的写法有以下几种写法:

(一)、selectByIdSet(List idList)

如果参数的类型是List, 则在使用时,collection属性要必须指定为 list

List<User> selectByIdSet(List idList);

<select id="selectByIdSet" resultMap="BaseResultMap">

  SELECT  <include refid="Base_Column_List" />

  FROM t_user

  WHERE id IN

  <foreach collection="list" item="id" index="index" open="(" close=")" separator=",">

  #{id}

  </foreach>

</select>

(二)、List<User> selectByIdSet(String[] idList)

如果参数的类型是Array,则在使用时,collection属性要必须指定为 array

List<User> selectByIdSet(String[] idList);

<select id="selectByIdSet" resultMap="BaseResultMap">

  SELECT

  <include refid="Base_Column_List" />

  FROM t_user

  WHERE id IN

  <foreach collection="array" item="id" index="index" open="(" close=")" separator=",">

  #{id}

  </foreach>

</select>

(三)、参数有多个时

当查询的参数有多个时,有两种方式可以实现,一种是使用@Param("xxx")进行参数绑定,另一种可以通过Map来传参数。

3.1 @Param("xxx")方式

List<User> selectByIdSet(@Param("name")String name, @Param("ids")String[] idList);

<select id="selectByIdSet" resultMap="BaseResultMap">

  SELECT

  <include refid="Base_Column_List" />

  FROM t_user

  WHERE name=#{name,jdbcType=VARCHAR} and id IN

  <foreach collection="idList" item="id" index="index"

      open="(" close=")" separator=",">

  #{id}

  </foreach>

</select>

3.2 Map方式

Map<String, Object> params = new HashMap<String, Object>(2);

params.put("name", name);

params.put("idList", ids);

mapper.selectByIdSet(params);

<select id="selectByIdSet" resultMap="BaseResultMap">

select

<include refid="Base_Column_List" />

from t_user where

name = #{name}

and ID in

<foreach item="item" index="index" collection="idList" open="(" separator="," close=")">

#{item}

</foreach>

</select>



©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容