目录
1. 前言
2. 适用于 MyBatis 框架
2.1 获取单条插入语句生成的ID
2.2 获取集合插入生成的多条数据的ID
3. 适用于 MyBatisPlus 框架
3.1 获取单条数据插入生成的ID
3.2 获取集合插入数据生成的多条数据的ID
4. 小结
1. 前言
在开发过程中,我们可能会遇到这样的一种情况,我们保存一条数据。
如果这条数据的主键ID是由用户决定的,这样我们在获取主键ID的时候,只需要让前端的同时传递给我们就可以了;
如果主键ID设置为自增,是在用户新增数据操作时自动生成的,在后续业务逻辑中需要使用生成的主键ID值,我们又该如何获取呢?本篇我们就来说说两种常用方法获取自动生成的主键ID;
2. 适用于 MyBatis 框架
2.1 获取单条插入语句生成的ID
在SQL映射文件中添加 useGeneratedKeys="true" keyProperty="id"
如下,我定义一个插入Product 实体接口
// @Mapper 注释标注当前类为数据访问层接口
@Mapper
public interface ProductMapper {// 定义一个插入接口Integer insertProduct(@Param("product") Product product);}
在对应的 ProductMappper.xml SQL映射语句中,只需要在 <insert> 中添加 useGeneratedKeys="true" keyProperty="id" 这两个属性即可。
SQL语句中并没有传入ID。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.haust.mapper.ProductMapper"><insert id="insertProduct" useGeneratedKeys="true" keyProperty="id" parameterType="com.haust.entity.Product">insert into product (`name`,`price`,`color`) values (#{product.productName},#{product.productPrice},#{product.productColor})</insert></mapper>
我们来做个测试,可以看到,创建的实体对象中我并没有传入ID值,只传递了 name,price,color 三个属性值
@Testpublic void testInsertProduct(){Product product = new Product();product.setProductName("电视机");product.setProductPrice(2000.00);product.setProductColor("red");productMapper.insertProduct(product);System.out.println(product);}
运行测试方法,就可以在控制台看到打印的商品信息,如下图,数据库自动生成的ID=14;
2.2 获取集合插入生成的多条数据的ID
在 ProductMapper 接口中自定义 insertAll 插入多条数据接口
@Mapper
public interface ProductMapper extends BaseMapper<Product> {Integer insertAll(@Param("productList") List<Product> productList);
}
在对应的 ProductMapper.xml 文件中编写对应的 SQL 语句,使用动态SQL语句的写法
<insert id="insertAll" parameterType="com.haust.entity.Product" useGeneratedKeys="true" keyProperty="id">insert into product (name,price,color)values<foreach collection="productList" item="product" separator="," >(#{product.productName},#{product.productPrice},#{product.productColor})</foreach>
</insert>
编写测试类
@Testpublic void testInsert(){ArrayList<Product> list = new ArrayList<Product>();Product product = new Product();product.setProductName("电脑");product.setProductPrice(5999.00);product.setProductColor("white");list.add(product);Product product2 = new Product();product2.setProductName("洗衣机");product2.setProductPrice(999.00);product2.setProductColor("red");list.add(product2);Product product3 = new Product();product3.setProductName("冰箱");product3.setProductPrice(1999.00);product3.setProductColor("black");list.add(product3);productMapper.insertAll(list);System.out.println(list);// 获取ID集合ArrayList<Long> ids = new ArrayList<Long>();list.forEach(item ->{ids.add(item.getId());});System.out.println(ids);}
运行方法,可以在控制台看到批量插入成功,并通过遍历获取到自动生成的ID集合;
3. 适用于 MyBatisPlus 框架
3.1 获取单条数据插入生成的ID
MyBatisPlus 框架自带的插入方法会在插入成功之后将方法回写到实体对象参数中;
我们都知道,MyBatisPlus 为提供了单表的增上改查方法,在MyBatis框架的基础上做了增强,我们仍以刚才的 Product 表为例,使用MyBatisPLus 实现获取自动生成主键ID。
第一步:修改实体类,添加注释
@Data
@TableName("product") // @TableName 注释是MyBatisPlus提供的注释,用于标注当前实体类对应数据库的哪张表
public class Product {// @TableId("id") 指定数据主键为 id,类型type为自增@TableId(value = "id", type = IdType.AUTO)private Long id;// @TableField("name") 标注当前String字段name为普通字段,对应product数据库表中的字段name,下方同理@TableField("name")private String productName;@TableField("price")private Double productPrice;@TableField("color")private String productColor;@TableField("production_date")private Date productionDate;
}
第二步:修改Mapper接口,继承BaseMappper接口
@Mapper
public interface ProductMapper extends BaseMapper<Product> {
}
单表增上改查接口都在BaseMapper接口中定义好了,直接继承使用即可,不需要写xml文件,除非是自定义新增接口需要额外写;
@Testpublic void testInsert(){Product product = new Product();product.setProductName("电脑");product.setProductPrice(6999.00);product.setProductColor("black");int insert = productMapper.insert(product);System.out.println(product);}
运行测试方法,打印 product 商品信息,可以发现我们没有传入主键ID的值,数据自动生成的ID=15,并写入到了 product 对象中,我们打印 product 就会显示出来ID,接上了刚才的14。
在实际的开发过程中,如果需要使用ID,在执行完插入操作之后,直接调用 product.getId() 即可获取到生成的主键ID值。
3.2 获取集合插入数据生成的多条数据的ID
MyBatisPlus 提供了多条插入数据,但是在 Service 业务层接口方法,mapper 层只提供了单条数据插入接口,要使用集合插入,需要继承 IService 接口,泛型为实体泛型 Product。
public interface ProductService extends IService<Product> {
}
实现类继承 ServiceImpl 类并添加两个泛型,第一个泛型填写对应的 Mapper 接口,第二个泛型填写对应的实体类 Product 泛型;
@Service
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements ProductService {
}
书写测试类
@Testpublic void testInsert(){ArrayList<Product> list = new ArrayList<Product>();Product product = new Product();product.setProductName("电脑");product.setProductPrice(6999.00);product.setProductColor("black");list.add(product);Product product2 = new Product();product2.setProductName("洗衣机");product2.setProductPrice(999.00);product2.setProductColor("black");list.add(product2);Product product3 = new Product();product3.setProductName("冰箱");product3.setProductPrice(1999.00);product3.setProductColor("black");list.add(product3);productService.saveBatch(list);System.out.println(list);// 获取ID集合ArrayList<Long> ids = new ArrayList<Long>();list.forEach(item ->{ids.add(item.getId());});}
运行测试类,打印 list 集合,如果要获取所有ID,遍历 list 集合即可,代码中我已经写好了,运行如下图,可以看到获取到了生成的ID集合。
4. 小结
其实上述两种方法没有本质区别,只是框架不一样。
如果在实际开发过程中,你的公司没有使用 MyBatisPlus 框架,那就选择第一种方法加入 useGeneratedKeys="true" keyProperty="id" 即可;
如果你的公司使用了 MyBatisPlus 框架,基本不需要做额外操作,因为实际开发过程中也很少会有插入语句需要去自定义的,直接使用 MyBatisPlus 提供的足以应对业务需求;