公司使用的 freemarker自定义代码生成模板,Mapper中在使用 SELECT * ,这无疑对性能造成了极大的影响,造成了很多不必要的IO读写。因此在想着改进一下代码,灵活的在使用中指定哪些字段需要查询,提升性能。
Builder模式
建造者模式(Builder Pattern)也叫做生成器模式,其定义如下:
Separate the construction of a complex object from its representation so that the same construction process can create different representations.
(将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。)
Builder 模式适用于需要多个构造方法,且参数不同的情况。
案例
Table
字段名称 | 字段类型 |
---|---|
id | Long |
content | String |
siteName | String |
原代码
查询条件Dto
@Setter
@Getter
public class DemoQueryDto {
private Long id;
private List<Long> ids;
private List<Long> idNotIn;
private Long idLike;
private Long idNotEquals;
private Long idIsNull;
private String content;
private List<String> contents;
private List<String> contentsNotIn;
private String contentLike;
private String contentNotEquals;
private String contentIsNull;
private String siteName;
private List<String> siteNames;
private List<String> siteNamesNotIn;
private String siteNameLike;
private String siteNameNotEquals;
private String siteNameIsNull;
}
Dao
/**
* 根据查询条件获取对应信息
* @param condition
* @return list
*/
List<DemoEntity> selectList(@Param("condition") DemoQueryDto condition);
Mapper
<sql id="Base_Column_List">
id, content, site_name
</sql>
..........省略
select <include refid="Base_Column_List" /> from A where 1=1
<include refid="Condition_Where" />
..........省略
<sql id="Condition_Where">
<if test="condition != null">
<if test="condition.id != null">
and id = #{condition.id,jdbcType=BIGINT}
</if>
<if test="condition.ids != null and condition.ids.size > 0">
and id in
<foreach item="item" collection="condition.ids" open="(" close=")" separator=",">
#{item}
</foreach>
</if>
<if test="condition.idsNotIn != null and condition.idsNotIn.size > 0">
and id not in
<foreach item="item" collection="condition.idsNotIn" open="(" close=")" separator=",">
#{item}
</foreach>
</if>
<if test="condition.idLike != null">
and id like concat('%',#{condition.idLike,jdbcType=BIGINT},'%')
</if>
<if test="condition.idNotEquals != null">
and id != #{condition.idNotEquals,jdbcType=BIGINT}
</if>
<if test="condition.idIsNull != null">
and id is null
</if>
..........类似省略
</if>
</sql>
Service
......参数等省略
DemoQueryDto queryDto = new DemoQueryDto();
queryDto.setIds(ids);
List<DemoEntity> demos = demoMapper.selectList(queryDto);
按照上述方法查询的时候,执行的Sql就是Select全部字段的Sql
Builder方法改造
@Getter
@Setter
public class DemoBuilderDto {
private DemoQueryDto demoQueryDto ;
//需要判断是否查询的字段
private boolean iscontent;
private boolean issiteName;
public static class Builder{
private DemoQueryDto demoQueryDto ;
//需要判断是否查询的字段 默认false
private boolean iscontent = false;
private boolean issiteName = false;
public Builder(){
}
public Builder DemoQueryDto (DemoQueryDto conditionQueryDto){
demoQueryDto = conditionQueryDto;
return this;
}
public Builder iscontent(boolean flag){
iscontent = flag;
return this;
}
public Builder issiteName(boolean flag){
issiteName = flag;
return this;
}
public DemoBuilderDto build(){
return new DemoBuilderDto (this);
}
}
private DemoBuilderDto (Builder builder){
demoQueryDto = builder.demoQueryDto ;
iscontent = builder.iscontent;
issiteName = builder.issiteName;
}
}
Mapper
<sql id="Base_Column_List">
id
<if test = "condition.iscontent == true">
,content
</if>
<if test = "condition.issiteName== true">
,site_name
</if>
</sql>
..........省略
select <include refid="Base_Column_List" /> from A where 1=1
<include refid="Condition_Where" />
..........省略
<sql id="Condition_Where">
<if test="condition != null">
<if test = "condition.demoQueryDto != null">
<if test="condition.demoQueryDto.id != null">
and id = #{condition.demoQueryDto.id,jdbcType=BIGINT}
</if>
..........类似省略
</if>
</if>
</sql>
Dao
List<DemoEntity> selectList(@Param("condition") DemoBuilderDto condition);
Service
DemoQueryDto queryDto = new DemoQueryDto();
queryDto.setIds(ids);
//现在我只需要查询content
DemoBuilderDto buildDto = new DemoBuilderDto
.Builder()
.demoQueryDto(queryDto)
.iscontent(true)
.build();
List<DemoEntity> demos = demoMapper.selectList(buildDto );