开启事务时mybatis返回主键id
先说一下没有注解的
先给出实体类:
public class City { private int city_id; private String city_name; public int getCity_id() { return city_id; } public void setCity_id(int city_id) { this.city_id = city_id; } public String getCity_name() { return city_name; } public void setCity_name(String city_name) { this.city_name = city_name; } @Override public String toString() { return "City [city_id=" + city_id + ", city_name=" + city_name + "]"; } }
以下为mysql的示例:
当我们插入一条数据的时候,需要创建一个对象,然后无论是在xml中,或者使用注解的形式,直接插入就可以了,但是需要创建一个对象来插入
这里我演示新增一个城市,为了简单,我就直接操作dao层了,按理来说应该从service中操作的:
@RequestMapping("/test") public void test(){ City c = new City(); c.setCity_name("赣州"); baseDao.addCity(c); System.out.println(c); }
上面是一个控制层,我直接new了一个城市的对象,但是并没有设置它的id,直接传到了dao层来操作,下面看dao层的代码:
@Insert("insert into t_city(city_name)values(#{city_name})") @SelectKey(statement="SELECT LAST_INSERT_ID()",keyProperty="city_id",before=false,resultType=Integer.class) public void addCity(City c);
@insert注解还是和往常一样,没有变化。
重要的是@SelectKey注解,是它完成了返回主键id的功能,上面来具体说明一下
statement这个属性,它是与数据库相关的,代表着查询主键id的功能,MySql是
SELECT LAST_INSERT_ID()
Oracle是
CALL IDENTITY()
keyProperty,代表着传入对象的主键id属性,所以之前说,传入的必须是一个对象,因为当插入完成后,mybaits会通过反射,掉用这个对象的set方法,把对应的id值set进去这个对象,然后在外部,就可以直接取这个对象的id属性了,这样就完成了返回主键的功能
可能 xml用的比较多一点,这里也给出xml的代码:
<insert id="insert" parameterType="实体类的地址"> insert into t_city (city_name) values (#{city_name}) <selectKey resultType="java.lang.Integer" keyProperty="city_id">
SELECT LAST_INSERT_ID()
</selectKey> </insert>
下面就是重头戏了
在有事务的时候,如何返回主键id呢?
大家都知道,开启事务的时候,是为了可以在发生异常的时候,回滚数据。那么由于这样的一个机制,在@transaction中的这个方法,如果没有执行完毕,是不会真正的操作数据库的,那么这个时候,既然没有在数据库里插入数据时候,怎么能知道数据库的主键id呢?
其实我在网上看到好多人都束手无策,但是其实是有办法解决了,mybaits真的非常强大。
下面给出xml的代码:
<insert id="addCity" parameterType="com.ujia.modular.base.dao.BaseDao" useGeneratedKeys="true" keyProperty="city_id"> insert into t_city(city_name)values(#{city_name}) </insert>
大家可能会惊讶的发现,这里的代码竟然更少了,但是实现的效果竟然是一样的,而且更加强大。它可以在事务中,得到主键id。那么上面的参数简单的说明一下
useGeneratedKeys是使用mybaits生成的key,这一步很重要,需要数据库支持自动生成才能做到。只要指定为true,那么mybaits就会从数据库中获取生成策略,然后计算后主键id,并且设置到该对象中,那么keyProperty就是之前说所的,标明主键id,在对象中的属性名称。
如果使用注解的话,依然可以保持上面的方式:
@Insert("insert into t_city(city_name)values(#{city_name})") @SelectKey(statement="SELECT LAST_INSERT_ID()",keyProperty="city_id",before=false,resultType=Integer.class) public void addCity(City c);
这里的一切代码,都是在mysql环境下测试的,本来并没有测试过oracle数据库,但是博主觉得肯定是可以的