最近要用springboot做一个项目,开始持久层使用的jpa,后来由于业务中涉及到很多不确定数据库字段,以及用户新增的表,用jpa无法完成需求,再加上在更新数据时,jpa会把属性为null的参数也更新,必须要再查一遍,然后拷贝属性后再更新,感觉很影响性能,无奈又用起了mybatis,又不想写mybatis的xml映射文件,遂又开始学注解方式,最开始碰到多参数,查询更新问题,网上查了很多资料写的很繁琐,而且又新增了很多配置文件,最后找了个最接近原xml配置的方式,记录如下:
一些准备工作
实体表,使用的是jpa的自动生成表,
@Entity(name = "sys_unit")
public class Unit extends Node {
/**
* (机构)部门名称
*/
private String unitName;
/**
* (机构)部门代号
*/
private String unitCode;
/**
* 排序字段
*/
private Integer unitSequence;
/**
* 类型0:内置根节点(只有一个不能新增,删除)1:公司,2:部门
*/
@Column(columnDefinition="enum('0','1','2') comment '类型'")
private String nuitType;
/**
* 启用状态1:启用,0:禁用,销毁
*/
@Column(columnDefinition="enum('1','0') comment '启用状态'")
private String unitActive;
/**
* 全宗号
*/
private String unitFonds;
/**
* 数据创建时间
*/
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss" )
@Column(nullable=false,columnDefinition="timestamp not null DEFAULT CURRENT_TIMESTAMP comment '创建时间'")
private LocalDateTime createTime;
/**
* 最后一次修改时间
*/
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss" )
@Column(nullable=false,columnDefinition="timestamp not null DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP comment '最后修改时间'")
private LocalDateTime updateTime;
}
因为我没有指定列名,最后在数据库中生成的字段会自动加下划线,如unit_name;所以在springbootd的application.yml配置文件中需要打开驼峰命名。
application.yml部分配置
mybatis:
configuration:
map-underscore-to-camel-case: true #打开驼峰命名
mapper
mapper文件是一个接口类,代替之前的xml映射文件;
具体写法如下
public interface UnitMapper {
/**
*增加部门
*/
@Insert("insert into sys_unit (" +
"id," +
"parent_id," +
"nuit_type," +
"unit_active," +
"unit_code," +
"unit_fonds," +
"unit_name," +
"unit_sequence)" +
" values( #{unit.id}," +
" #{unit.parentId},#{unit.nuitType},#{unit.unitActive}," +
" #{unit.unitCode},#{unit.unitFonds},#{unit.unitName}," +
" #{unit.unitSequence}) " )
int add(@Param("unit") Unit unit);
/**
*多参数查询部门信息
*/
@Select(" <script> SELECT id," +
"parent_id," +
"nuit_type," +
"unit_active," +
"unit_code," +
"unit_fonds," +
"unit_name," +
"unit_sequence"+
" from sys_unit WHERE " +
"1+1 "+
" <if test=\"unit.id != null \"> and id = #{unit.id} </if> "+
" <if test=\"unit.parentId != null \"> and parent_id = #{unit.parentId} </if> "+
" <if test=\"unit.unitName != null \"> and unit_name like CONCAT('%',#{unit.unitName},'%') </if> </script>")
List<Unit> query(@Param("unit") Unit unit);
/**
*更新
*/
@Update("<script> update sys_unit " +
"<trim prefix=\"set\" suffixOverrides=\",\">" +
" <if test=\"unit.parentId != null \"> parent_id = #{unit.parentId} ,</if> "+
" <if test=\"unit.unitName != null \"> unit_name = #{unit.unitName} ,</if> "+
" <if test=\"unit.nuitType != null \"> nuit_type = #{unit.nuitType} ,</if> "+
" <if test=\"unit.unitFonds != null \"> unit_fonds = #{unit.unitFonds} ,</if> "+
" <if test=\"unit.unitCode != null \"> unit_code = #{unit.unitCode} ,</if> "+
" </trim> "+
" where id = #{unit.id} </script>")
int updata(@Param("unit") Unit unit);
}
<trim></trim>标签的用法和以前的xml配置文件里的写法一致,
- 新增方法里,@Param注解javaBean ,在sql语句里用#{注解名字.属性名进行引用}
- 在查询方法里,因为涉及到不确定的查询条件,需要用到进行判断,这里需要注意的是sql语句需要用<script></script>包裹。
- 1+1这里是凑一个条件,让后面的条件都要写and,不用再去条件判断,当然你也可以用<trim></trim>标签代替,参见更新方法
- 更新方法里<trim prefix=“set” suffixOverrides=","></trim>标签里,prefix代表最开始加个set ; suffixOverrides代表去掉最后的逗号;当然也有在开始去掉,以及再最后增加字符串的方法,这个需要请自行查阅相关资料,这里不过多说明(其实是我也不知道,手动滑稽);
算了还是要图片滑稽采才够正式。(`・ω・´)
好了还有最后的一步,在springboot的启动类上加入mapper接口所在包的路径,
//扫描mybatis接口
//( ̄︶ ̄)↗(敲黑板),看这里,在@MapperScan写上你的接口文件所在的包的路径,springboot在启动时就会自动扫描
@MapperScan("com.XXX.XXX.mapper")
@SpringBootApplication
public class SfmsApplication {
public static void main(String[] args) {
SpringApplication.run(SfmsApplication.class, args);
}
}
好了大功告成,再写个单元测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class UnitMapperTest {
@Autowired
private UnitMapper unitMapper;
/**
* 根据ID,多条件更新测试
*/
@Test
public void updata(){
Unit u = new Unit();
u.setId("0006");
u.setUnitName("测试06");
unitMapper.add(u);
Unit u1 = unitMapper.query(u).get(0);
assertEquals(u1.getUnitName(),"测试06");
u1.setUnitName("修改测试06");
u1.setUnitCode("TEST06");
unitMapper.updata(u1);
Unit u2 =unitMapper.query(u1).get(0);
assertEquals(u2.getUnitName(),"修改测试06");
assertEquals(u2.getUnitCode(),"TEST06");
}
}
首先创建个部门对象设置ID为0006,名称为测试06,然后执行add添加这个对象到数据库
,然后在根据这个对象为条件执行查询,因为ID是唯一的,所以list里只有一个,直接get(0)拿出来,断言这个部门名称为测试06,然后再修改这个对象的两个属性,执行更新方法,再根据修改后的对象去数据库中查询,断言修改后的属性。好了执行成功。