在springboot框架下使用mybatis开发遇到的一些问题以及解决方案(postgresql数据库)

本文所用的springboot版本为2.0,所用的mybatis版本为2.0

1.@mapper和@mapperscan。二者的作用是一样的,如果不想在每个mapper上加@mapper,就直接使用@mapperscan。

2.使用mybatis自动生成mapper时,如果生成多次,会直接在mapper.xml文件里面追加重复代码。

3.mybatis自动生成的mapper.xml文件需要配置一下,才能正确加载:

mybatis.mapper-locations=classpath:/mapper/*.xml(写在application.properties里面)

否则会报错:Invalid bound statement (not found)

4.mybatis自动生的example是和model一个命名空间下的,它们实际上并不是一个东西,需要分开。但是mybatis目前还不支持分开,需要手动把example放到其他命名空间下。注意修改一下自动生成的mapper.xml文件,不然会报错,因为ide不提示这里面的错误。

5.mybatis不支持uuid,而且代码中习惯将uuid当作string类型来处理,这个时候需要在mybatis自动生成的时候重写一下uuid类型的列。方法如下:


同时针对这种mybatis不支持的数据类型,你还需要用到typehandler,具体typehandler可参考官方文档,这里提供一个我写好的将postgresql里面的uuid[]转换成java里面的list的handler写法,其中mybatis是VARCHAR类型的:

@MappedJdbcTypes(JdbcType.VARCHAR)
public class ArrayToStringListHandler extends BaseTypeHandler> {
    @Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, List strings, JdbcType jdbcType) throws SQLException {
        String str=String.join(",",strings);
        //postgresql数组是以{}开始的
        str="{"+str+"}";
        preparedStatement.setString(i, str);
    }

    @Override
    public List getNullableResult(ResultSet resultSet, int i) throws SQLException {
        return null;
    }

    @Override
    public List getNullableResult(ResultSet resultSet, String s) throws SQLException {
        java.sql.Array array= resultSet.getArray(s);
        if (array==null) return null;
        List list=new LinkedList<>();
        for (Object o:(Object[]) array.getArray())
        {
            list.add(o.toString());
        }
        return  list;
    }

    @Override
    public List getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
        return null;
    }
}

8.mybatis里面example类型强制转换的问题,有些字段的类型比较特殊,比如id经常用uuid,这个时候生成的sql语句要加上::uuid才行(postgresql语法),但是example不直接支持增加类型强制转换,这里我想到的解决办法是修改mybatis自动生成的源代码,方法如下:

a)首先要在example文件里面找到Criterion这个类,在里面加上一个属性property,这个是用来标识你的属性名的,根据你的属性名来判断哪些地方需要加上强制转换。

private String property;

public String getProperty() {
    return property;
}

public void setProperty(String property) {
    this.property = property;
}

b)然后修改特殊类型字段条件方法,比如我用的数据库是postgresql,而我的id是uuid类型的。最初mybatis生成的方法是这样的

public Criteria andIdNotEqualTo(String value) {
    addCriterion("id <>", value, "id");
    return (Criteria) this;
}

这个方法是给sql加上id不等于某个值的条件,因为我传进去的是字符串,如果不加::uuid转换,数据库会报错。既然我们已经把属性名id传进去了,所以我们修改一下addCriterion这个方法,它原本是这样的

protected void addCriterion(String condition, Object value, String property) {
    if (value == null) {
        throw new RuntimeException("Value for " + property + " cannot be null");
    }
    Criterion criterion=new Criterion(condition, value);
    criteria.add(criterion);
}

我们加一句: criterion.setProperty(property);让它变成这样

protected void addCriterion(String condition, Object value, String property) {
    if (value == null) {
        throw new RuntimeException("Value for " + property + " cannot be null");
    }
    Criterion criterion=new Criterion(condition, value);
    criterion.setProperty(property);
    criteria.add(criterion);
}

c)这个时候,传给mapper.xml的Criterion 就带有属性名了,然后把mapper.xml里面的Example_Where_Clause,或者其他用到example的语句改一下,改成这样


  and ${criterion.condition} #{criterion.value}::uuid


  and ${criterion.condition} #{criterion.value}

你会注意到我这里面加了一个判断:and criterion.property=='id',也就是说当属性是id的时候,我要给语句sql上加一个::uuid的转换。其他的则不加。这样,就解决了example特殊类型转换的问题了。当然,更复杂的逻辑,可能xml里面的条件判断要复杂一些。然后你再使用example的时候还像原来那样正常使用就可以了:

UserExample example = new UserExample();
example.createCriteria().andIdNotEqualTo(user.getId());
int count = userMapper.countByExample(example);

9.restful风格的接口允许传null值进来的问题。这个问题的解决方式是用map接收body,而不再是实体类。如果你用实体类接收,那么你就无法区分是用户传给了你null,还是因为用户没有传导致的null值了。用map接收则没有这个问题,你可以判断map中是否包含这个key,如果包含就表示用户要修改,如果不包含,就表示用户不打算修改,至于所传的值是不是null,你则不需要关心。这样的话,mybatis的mapper应该像下面这么写:


  update public.status
  
    
      name = #{name,jdbcType=VARCHAR},
    
    
      remarks = #{remarks,jdbcType=VARCHAR},
    
  
  where id = #{id,jdbcType=VARCHAR}

判断是否包含该键,如果包含则更新。

你可能感兴趣的:(在springboot框架下使用mybatis开发遇到的一些问题以及解决方案(postgresql数据库))