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次

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}

)

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

mapping.xml

insert into student ( )

values

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

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

foreach>

参数解释:

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 getEmpsByConditionLike(@Param("list")List 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 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 list = (List) 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有什么关键字

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

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

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

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

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

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

close 表示以什么结束。

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

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

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

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

1)添加SQL映射语句

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

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

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

public List selectUserByForeach(List listId);

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

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

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

List listId=new ArrayList();

listId.add(34);

listId.add(37);

List 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怎样实现主键自增呢?

  

            select student_sequence.nextval from dual

       

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

或者

   

        SELECT SEQ_ZONE.CURRVAL AS id from dual

   

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



4.如何使用in

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

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

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

Map selectByUserId(@Param("useType") String useType)

其中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 selectByIdSet(List idList);

(二)、List selectByIdSet(String[] idList)

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

List selectByIdSet(String[] idList);

(三)、参数有多个时

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

3.1 @Param("xxx")方式

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

3.2 Map方式

Map params = new HashMap(2);

params.put("name", name);

params.put("idList", ids);

mapper.selectByIdSet(params);



你可能感兴趣的:(mybatis)