关于数据库Dao层传值问题和SQL与POJO映射关系

关于数据库Dao层传值问题和SQL与POJO映射关系。

写这篇文章的背景是我在实现一个项目的模块进行联调测试的时候,发现时间在前端不显示。
原因是数据库处理出现了问题。

插入操作pojo字段和占位符名字不一致

代码示例

1
2
3
@Insert("insert into emp (username, name, gender, image, job, entrydate, dept_id, create_time, update_time)"+
" VALUES(#{username},#{name},#{gender},#{image},#{job},#{entrydate},#{deptId},#{createTime},#{updateTime}) ")
void insert(Emp emp);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Emp {
public Integer id;
private String username;
private String password;
private String name;
private Short gender;
private String image;
private Short job;
private LocalDate entrydate;
private Integer deptId;
private LocalDateTime createTime;
private LocalDateTime updateTime;
}

解决方案

问题发生在我的pojo类中的字段没有和VALUES(#{username},#{name},#{gender},#{image},#{job},#{entrydate},#{deptId},#{createTime},#{updateTime})正确绑定,比如字段是entryDate但是占位符是#{entrydate}。

[!Tip]
增加和改要注意,因为一般传入的是一个pojo示例,涉及全字段。

查询操作数据库字段和pojo字段不一致

示例代码

由此引出另一个注意事项,在查询的时候可能涉及字段未传上。

1
2
@Select("select * from emp where id = #{id}")
Emp selectById(Integer id);

显然,数据库表的设计并不是和pojo实体完全一样,所以存在无法映射。

解决方案

  1. 使用@Results,为不一致的绑定关系。

    1
    2
    3
    4
    5
    6
    7
    @Results({
    @Result(column = "dept_id" ,property = "deptId"),
    @Result(column = "create_time",property = "createTime"),
    @Result(column = "update_time",property = "updateTime")
    })
    @Select("select * from emp where id = #{id}")
    Emp selectById(Integer id);
  2. 起别名,只不过要出写出完整sql。虽然会繁琐但也是好处的,他比*速度更快。

  3. 在SpringBoot开启驼峰命名设置。

1
2
# 在application.properties中添加:
mybatis.configuration.map-underscore-to-camel-case=true`

数据库一般都是xxx_xxx,所以在pojo设置字段xxxXxx

多参数问题

代码示例

还有一种多参数的情况,即Dao层访问数据库的方法带多个参数。这时候要用@Param给形参起名字,保证SQL能够正确识别。

1
2
3
4
List<Emp> page(@Param("name") String name,
@Param("gender") Short gender,
@Param("begin") LocalDate begin,
@Param("end") LocalDate end);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<select id="page" resultType="camellia.pojo.Emp">
select id, username,password,name,gender,image,job,entrydate as entrydate,
dept_id as deptId,create_time as createTime,update_time as updateTime from emp
<where>
<if test="name != null and name != ''">
name like concat ('%',#{name},'%')
</if>
<if test="gender != null">
and gender = #{gender}
</if>
<if test="begin != null and end != null">
and entrydate between #{begin} and #{end}
</if>
</where>
order by update_time desc
</select>

解决方案

如果不起别名直接传入控制台会报name参数找不到,可用的参数包括[arg1, arg0, param1, param2]@Param之类的信息。原因是Mybatis底层实际上在mybatis底层会创建一个map集合,以arg0/param1为key,以方法上的参数为value。所以使用@Param就相当于给key起名字,使SQL能正确识别。