如何将JPA实体类转为DTO/POJO解决Sonar提示的代码漏洞问题?
问题原因
Sonar要求你避免直接将JPA持久化实体类作为Controller层的请求/响应对象,核心是因为JPA实体绑定了数据库映射逻辑,直接对外暴露会带来参数恶意注入、数据库结构泄露、关联对象序列化异常等风险,所以需要用纯普通Java对象(DTO)来做API层的入参载体。
解决方案步骤
1. 定义MissionDTO类
只保留API接口实际需要接收的字段,这里新增mission业务只需要前端传入name和description,不需要id、关联的departement、timesheets字段:
public class MissionDTO { private String name; private String description; // 空构造方法必写,用于Spring反序列化请求参数 public MissionDTO() { } public MissionDTO(String name, String description) { this.name = name; this.description = description; } // Getter和Setter public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } }
2. 编写DTO与实体类的转换逻辑
你可以选择手动转换(适合字段少的场景)或者用MapStruct等工具类自动转换,以下是手动转换的示例:
// 可以放在工具类里,也可以写在DTO静态方法中 public class MissionConverter { public static Mission toEntity(MissionDTO dto) { if (dto == null) { return null; } Mission mission = new Mission(); mission.setName(dto.getName()); mission.setDescription(dto.getDescription()); // 其余字段如id、关联对象由业务层处理,不允许前端传入 return mission; } // 如果需要返回实体数据给前端,也可以写转DTO的方法 public static MissionDTO toDTO(Mission entity) { if (entity == null) { return null; } MissionDTO dto = new MissionDTO(); dto.setName(entity.getName()); dto.setDescription(entity.getDescription()); return dto; } }
3. 修改RestController代码
将入参替换为MissionDTO,转换为实体后再调用业务逻辑:
@PostMapping("/ajouterMission") @ResponseBody public int ajouterMission(@RequestBody MissionDTO missionDTO) { Mission mission = MissionConverter.toEntity(missionDTO); try { logger.info("in ajouter Mission"); logger.debug("Je vais commencer l'ajout"); itimesheetservice.ajouterMission(mission); logger.info("out ajouter Mission"); return mission.getId(); } catch (Exception e) { logger.error("Erreur dans ajouterMission() : " , e); } return mission.getId(); }
优化说明
如果项目中DTO和实体转换场景较多,推荐使用MapStruct框架自动生成转换代码,避免手动编写大量重复的Getter/Setter赋值逻辑。
内容的提问来源于stack exchange,提问作者Dr.Dev1998
相关产品推荐
相关产品推荐

