MyBatis 3.3.1 版本新功能示例

MyBatis 3.3.1版本新功能示例

MyBatis3.3.1更新日志:
https://github.com/mybatis/mybatis-3/issues?q=milestone%3A3.3.1

这里不对更新做翻译或者其他详细介绍。
这个更新除了一些bug修复,还有两个新增的功能:

  • 增加了对批量插入回写自增主键的功能
  • 增加了注解引用@Results的功能

下面通过简单例子来介绍这两个功能,为了例子的简洁,这里都使用注解实现的,没有用XML,批量插入的例子很容易就能变成XML形式的,大家自己尝试。

先看基础的表和对应的POJO。

city表:

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for city
-- ----------------------------
DROP TABLE IF EXISTS `city`;
CREATE TABLE `city` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(255) CHARACTER SET utf8 DEFAULT NULL, `state` varchar(255) CHARACTER SET utf8 DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;

-- ----------------------------
-- Records of city
-- ----------------------------
INSERT INTO `city` VALUES ('1', '石家庄', '河北');
INSERT INTO `city` VALUES ('2', '邯郸', '河北');

city对象:

public class City2 {
    private Integer id;

    private String cityName;

    private String cityState;

    public City2() {
    }

    public City2(String cityName, String cityState) {
        this.cityName = cityName;
        this.cityState = cityState;
    }

    //省略setter,getter

    @Override
    public String toString() {
        return "City2{" +
                "id=" + id +
                ", cityName='" + cityName + '\'' +
                ", cityState='" + cityState + '\'' +
                '}';
    }
}

定义如下MyBatis331Mapper接口

/** * mybatis3.3.1版本新增功能测试 * * @author liuzh * @since 2016-03-06 17:22 */
public interface MyBatis331Mapper {

    /** * 批量插入 * * @param cities * @return */
    @Insert("<script>" +
            "insert into city (id, name, state) values " +
            "<foreach collection=\"list\" item=\"city\" separator=\",\" >" +
                "(#{city.id}, #{city.cityName}, #{city.cityState})" +
            "</foreach>" +
            "</script>")
    @Options(useGeneratedKeys = true, keyProperty = "id")
    int insertCities(List<City2> cities);

    /** * 根据主键查询一个 * * @param id * @return */
    @Results(id = "cityResult", value = {
        @Result(property = "id", column = "id", id = true),
        @Result(property = "cityName", column = "name", id = true),
        @Result(property = "cityState", column = "state", id = true)
    })
    @Select("select id, name, state from city where id = #{id}")
    City2 selectByCityId(Integer id);

    /** * 查询全部,引用上面的Results * * @return */
    @ResultMap("cityResult")
    @Select("select id, name, state from city")
    List<City2> selectAll();
}

这里详细说一下这两个新功能的用法。

先看批量插入的例子

@Insert("<script>" +
        "insert into city (id, name, state) values " +
        "<foreach collection=\"list\" item=\"city\" separator=\",\" >" +
            "(#{city.id}, #{city.cityName}, #{city.cityState})" +
        "</foreach>" +
        "</script>")
@Options(useGeneratedKeys = true, keyProperty = "id")
int insertCities(List<City2> cities);

首先接口参数只能有一个(默认情况下),如果你参数有多个,那么要返回主键的那个List必须加注解@Param("list")或者在参数Map中对应的key"list"。这一点很重要,只有看源码才能了解(当然除了"list"还有另外的名字,例如支持数组的"array"),参考Jdbc3KeyGenerator类中的这段代码:

if (parameterMap.containsKey("collection")) {
    parameters = (Collection) parameterMap.get("collection");
} else if (parameterMap.containsKey("list")) {
    parameters = (List) parameterMap.get("list");
} else if (parameterMap.containsKey("array")) {
    parameters = Arrays.asList((Object[]) parameterMap.get("array"));
}

然后就是必须使用useGeneratedKeys的方式,注解使用下面的方式:

@Options(useGeneratedKeys = true, keyProperty = "id")

XML使用类似下面的方式:

<insert id="insertList" useGeneratedKeys="true" keyProperty="id">

只要注意上面这几点,批量插入应该就能返回自增的值了。

注意:大家应该能理解,自增的不一定是主键,而且一个表中可能有多个自增的值。这些情况下都能获取到,keyProperty需要设置多个属性值,逗号隔开即可。

再看引用@Results

(此功能是否为新增功能,我并不确定,因为我平时不用注解)

用MyBatis的人中,使用注解的是少数,但是有些企业由于领导或者别的原因,会限制必须用注解。

这对一些复杂的情况来说,使用起来不如XML的方便,但是不得不用。

以前如果返回一个对象的属性需要配置映射,那么每个对象上都需要这段重复的代码,看起来很乱很麻烦。

在上面的例子中,在selectByCityId上定义了Results,在下面的方法selectAll上通过@ResultMap("cityResult")直接引用的上面的Results。这个功能在使用的时候没有特别注意的地方。

测试

写个简单的测试,代码如下:

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@Transactional
@SpringApplicationConfiguration(Application.class)
public class MyBatis331Test {
    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private MyBatis331Mapper mapper;

    @Test
    @Rollback
    public void testInsertList() {
        List<City2> city2List = new ArrayList<City2>();
        city2List.add(new City2("石家庄", "河北"));
        city2List.add(new City2("邯郸", "河北"));
        city2List.add(new City2("秦皇岛", "河北"));
        Assert.assertEquals(3, mapper.insertCities(city2List));
        for (City2 c2 : city2List) {
            logger.info(c2.toString());
            Assert.assertNotNull(c2.getId());
        }
    }

    @Test
    public void testSelectById(){
        City2 city2 = mapper.selectByCityId(1);
        logger.info(city2.toString());
        Assert.assertNotNull(city2);
        Assert.assertNotNull(city2.getCityName());
        Assert.assertNotNull(city2.getCityState());
    }

    @Test
    public void testSelectAll(){
        List<City2> city2List = mapper.selectAll();
        for(City2 c2 : city2List){
            logger.info(c2.toString());
            Assert.assertNotNull(c2);
            Assert.assertNotNull(c2.getCityName());
            Assert.assertNotNull(c2.getCityState());
        }
    }

}

第一个测试方法输出的部分日志如下:

==>  Preparing: insert into city (id, name, state) values (?, ?, ?) , (?, ?, ?) , (?, ?, ?) ==> Parameters: null, 石家庄(String), 河北(String), null, 邯郸(String), 河北(String), null, 秦皇岛(String), 河北(String) <== Updates: 3 City2{id=6, cityName='石家庄', cityState='河北'} City2{id=7, cityName='邯郸', cityState='河北'} City2{id=8, cityName='秦皇岛', cityState='河北'}

后两个方法输出的部分日志如下:

==>  Preparing: select id, name, state from city where id = ? ==> Parameters: 1(Integer) <== Total: 1 City2{id=1, cityName='石家庄', cityState='河北'} ==> Preparing: select id, name, state from city ==> Parameters: <== Total: 2 City2{id=1, cityName='石家庄', cityState='河北'} City2{id=2, cityName='邯郸', cityState='河北'}

注:由于批量插入事务并没有提交,因此这里查询出来的结果就是表中原有的两条数据。

最后

为了方便尝试上面的代码,可以直接查看下面项目的src/test

MyBatis-Spring-Boot: https://github.com/abel533/MyBatis-Spring-Boot

另外mybatis-spring项目也同时更新到了1.2.4,这个版本对于使用SpringBoot的开发人员非常有用,这个版本解决了mybatis的循环依赖异常,如果你在使用SpringBoot,赶紧升级到最新的版本试试吧。

你可能感兴趣的:(mybatis)