springboot+jpa@Query使用方法,返回参数为List类型

数据库查询语句如下

午餐详情统计
SELECT
  STAFF.STAFF_NAME AS "姓名",
 ORGAN.NAME AS "部门",
 STAFF.STAFF_NO AS "工号",
 ALOG.OPEN_TIME AS "刷卡时间"
--   ALOG.OWNER_ID AS "食堂"
FROM
 T_ACCESS_LOG ALOG
 LEFT JOIN T_STAFF STAFF ON ALOG.ACCESS_CARD_NO = staff.STAFF_NO
 LEFT JOIN T_ORGAN ORGAN on STAFF.ORGAN_ID = ORGAN.id
WHERE
ALOG.ACCESS_CARD_NO = STAFF.STAFF_NO
AND ALOG.STAFF_NAME = STAFF.STAFF_NAME
-- AND STAFF.status = 1
AND (ALOG.OWNER_ID = 72324)
AND ALOG.OPEN_TIME BETWEEN TO_DATE (
  '2021-11-01 00:00:00',
 'yyyy-mm-dd hh24:mi:ss'
)
AND TO_DATE (
 '2021-11-30 23:59:59',
 'yyyy-mm-dd hh24:mi:ss'
)
AND TO_CHAR(ALOG.OPEN_TIME, 'hh24:mi:ss') BETWEEN '10:30:00' AND  
       '14:00:00' 
ORDER BY
  ALOG.OPEN_TIME ASC

 ;
 
 
午餐次数统计:
 SELECT
	TEMP."NAME" AS "部门",
	TEMP.STAFF_NAME AS "姓名",
	count( * ) AS "总数" 
FROM
	(
	SELECT
		STAFF.STAFF_NAME,
		ORGAN.NAME,
		TO_CHAR( ALOG.OPEN_TIME, 'yyyy-mm-dd' ) 
	FROM
		T_ACCESS_LOG ALOG
		LEFT JOIN T_STAFF STAFF ON ALOG.ACCESS_CARD_NO = staff.STAFF_NO
		LEFT JOIN T_ORGAN ORGAN on STAFF.ORGAN_ID = ORGAN.id
	WHERE
		ALOG.ACCESS_CARD_NO = STAFF.STAFF_NO
		AND ALOG.STAFF_NAME = STAFF.STAFF_NAME
-- 		AND STAFF.status = 1
		AND ALOG.OWNER_ID = '72324' 
		AND ALOG.OPEN_TIME BETWEEN TO_DATE( '2021-11-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss' ) 
		AND TO_DATE( '2021-11-30 23:59:59', 'yyyy-mm-dd hh24:mi:ss' ) 
		AND TO_CHAR( ALOG.OPEN_TIME, 'hh24:mi:ss' ) BETWEEN '10:30:00' 
		AND '14:00:00' 
	GROUP BY
		STAFF.STAFF_NAME,
		ORGAN.NAME,
		TO_CHAR( ALOG.OPEN_TIME, 'yyyy-mm-dd' )
	) TEMP 
GROUP BY
	TEMP.STAFF_NAME,
	TEMP."NAME";
	
午餐按天统计总数:
SELECT
	TEMP.day AS "日期",
	count(* ) AS "次数" 
FROM
	(
	SELECT
		STAFF.STAFF_NAME,
		ORGAN.NAME,
-- 		AlOG.OPEN_TIME
		TO_CHAR( ALOG.OPEN_TIME, 'yyyy-mm-dd' ) AS day
		
	FROM
		T_ACCESS_LOG ALOG
		LEFT JOIN T_STAFF STAFF ON ALOG.ACCESS_CARD_NO = staff.STAFF_NO
		LEFT JOIN T_ORGAN ORGAN on STAFF.ORGAN_ID = ORGAN.id
	WHERE
		ALOG.ACCESS_CARD_NO = STAFF.STAFF_NO 
		AND ALOG.STAFF_NAME = STAFF.STAFF_NAME
-- 		AND STAFF.status = 1
		AND ALOG.OWNER_ID = '72324' 
		AND ALOG.OPEN_TIME BETWEEN TO_DATE( '2021-11-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss' ) 
		AND TO_DATE( '2021-11-30 23:59:59', 'yyyy-mm-dd hh24:mi:ss' ) 
		AND TO_CHAR( ALOG.OPEN_TIME, 'hh24:mi:ss' ) BETWEEN '10:30:00' 
		AND '14:00:00' 
	GROUP BY
		STAFF.STAFF_NAME,
		ORGAN.NAME,
-- 		ALOG.OPEN_TIME
-- -- 		,
		TO_CHAR( ALOG.OPEN_TIME, 'yyyy-mm-dd' )
	) TEMP 
GROUP BY
TEMP.day
-- TO_CHAR( TEMP.OPEN_TIME, 'yyyy-mm-dd' )
ORDER BY TEMP.day ASC;

晚餐详情统计:
SELECT
  STAFF.STAFF_NAME AS "姓名",
 ORGAN.NAME AS "部门",
 STAFF.STAFF_NO AS "工号",
 ALOG.OPEN_TIME AS "刷卡时间"
--   ALOG.OWNER_ID AS "食堂"
FROM
 T_ACCESS_LOG ALOG
 LEFT JOIN T_STAFF STAFF ON ALOG.ACCESS_CARD_NO = staff.STAFF_NO
 LEFT JOIN T_ORGAN ORGAN on STAFF.ORGAN_ID = ORGAN.id
WHERE
ALOG.ACCESS_CARD_NO = STAFF.STAFF_NO
 AND ALOG.STAFF_NAME = STAFF.STAFF_NAME
-- AND STAFF.status = 1
AND (ALOG.OWNER_ID = 72324)
AND ALOG.OPEN_TIME BETWEEN TO_DATE (
  '2021-11-01 00:00:00',
 'yyyy-mm-dd hh24:mi:ss'
)
AND TO_DATE (
 '2021-11-30 23:59:59',
 'yyyy-mm-dd hh24:mi:ss'
)
AND TO_CHAR(ALOG.OPEN_TIME, 'hh24:mi:ss') BETWEEN '17:30:00' AND  
       '21:00:00' 
ORDER BY
  ALOG.OPEN_TIME ASC

 ;

晚餐就餐次数统计:
SELECT
	TEMP."NAME" AS "部门",
	TEMP.STAFF_NAME AS "姓名",
	count( * ) AS "总数" 
FROM
	(
	SELECT
		STAFF.STAFF_NAME,
		ORGAN.NAME,
		TO_CHAR( ALOG.OPEN_TIME, 'yyyy-mm-dd' ) 
	FROM
		T_ACCESS_LOG ALOG
		LEFT JOIN T_STAFF STAFF ON ALOG.ACCESS_CARD_NO = staff.STAFF_NO
		LEFT JOIN T_ORGAN ORGAN on STAFF.ORGAN_ID = ORGAN.id
	WHERE
		ALOG.ACCESS_CARD_NO = STAFF.STAFF_NO
		AND ALOG.STAFF_NAME = STAFF.STAFF_NAME
-- 		AND STAFF.status = 1
		AND ALOG.OWNER_ID = '72324' 
		AND ALOG.OPEN_TIME BETWEEN TO_DATE( '2021-11-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss' ) 
		AND TO_DATE( '2021-11-30 23:59:59', 'yyyy-mm-dd hh24:mi:ss' ) 
		AND TO_CHAR( ALOG.OPEN_TIME, 'hh24:mi:ss' ) BETWEEN '17:30:00' 
		AND '21:00:00' 
	GROUP BY
		STAFF.STAFF_NAME,
		ORGAN.NAME,
		TO_CHAR( ALOG.OPEN_TIME, 'yyyy-mm-dd' )
	) TEMP 
GROUP BY
	TEMP.STAFF_NAME,
	TEMP."NAME";
	
晚餐按天统计:
SELECT
	TEMP.day AS "日期",
	count(* ) AS "次数" 
FROM
	(
	SELECT
		STAFF.STAFF_NAME,
		ORGAN.NAME,
-- 		AlOG.OPEN_TIME
		TO_CHAR( ALOG.OPEN_TIME, 'yyyy-mm-dd' ) AS day
		
	FROM
		T_ACCESS_LOG ALOG
		LEFT JOIN T_STAFF STAFF ON ALOG.ACCESS_CARD_NO = staff.STAFF_NO
		LEFT JOIN T_ORGAN ORGAN on STAFF.ORGAN_ID = ORGAN.id
	WHERE
		ALOG.ACCESS_CARD_NO = STAFF.STAFF_NO 
		AND ALOG.STAFF_NAME = STAFF.STAFF_NAME
-- 		AND STAFF.status = 1
		AND ALOG.OWNER_ID = '72324' 
		AND ALOG.OPEN_TIME BETWEEN TO_DATE( '2021-11-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss' ) 
		AND TO_DATE( '2021-11-30 23:59:59', 'yyyy-mm-dd hh24:mi:ss' ) 
		AND TO_CHAR( ALOG.OPEN_TIME, 'hh24:mi:ss' ) BETWEEN '17:30:00' 
		AND '21:00:00' 
	GROUP BY
		STAFF.STAFF_NAME,
		ORGAN.NAME,
-- 		ALOG.OPEN_TIME
-- -- 		,
		TO_CHAR( ALOG.OPEN_TIME, 'yyyy-mm-dd' )
	) TEMP 
GROUP BY
TEMP.day
-- TO_CHAR( TEMP.OPEN_TIME, 'yyyy-mm-dd' )
ORDER BY TEMP.day ASC;
-- 	TEMP."NAME";


	

整理一下,双引号都改成\",把所有回车删了,弄成一整行。

用List<Map<String,Object>>接收返回的List参数。

@Query中的参数,nativeQuery = true,value是对应的数据库语句。


    @Query(value = " SELECT TEMP.\"NAME\" AS \"dept\",TEMP.STAFF_NAME AS \"name\",count( * ) AS \"count\" FROM (SELECT	STAFF.STAFF_NAME,	ORGAN.NAME,	TO_CHAR( ALOG.OPEN_TIME, 'yyyy-mm-dd' ) 	FROM	T_ACCESS_LOG ALOG		LEFT JOIN T_STAFF STAFF ON ALOG.ACCESS_CARD_NO = staff.STAFF_NO		LEFT JOIN T_ORGAN ORGAN on STAFF.ORGAN_ID = ORGAN.id 	WHERE 		ALOG.ACCESS_CARD_NO = STAFF.STAFF_NO 		AND ALOG.STAFF_NAME = STAFF.STAFF_NAME 		AND ALOG.OWNER_ID = '72324'  		AND ALOG.OPEN_TIME BETWEEN TO_DATE( :startDateTime, 'yyyy-mm-dd hh24:mi:ss' )  AND TO_DATE( :endDateTime, 'yyyy-mm-dd hh24:mi:ss' )  		AND TO_CHAR( ALOG.OPEN_TIME, 'hh24:mi:ss' ) BETWEEN '10:30:00'  		AND '14:00:00'  	GROUP BY 		STAFF.STAFF_NAME, 		ORGAN.NAME, 		TO_CHAR( ALOG.OPEN_TIME, 'yyyy-mm-dd' ) 	) TEMP  GROUP BY 	TEMP.STAFF_NAME, 	TEMP.\"NAME\"",nativeQuery = true)
    public List<Map<String,Object>> lunchMealTimesByCount(@Param("startDateTime") String startDateTime, @Param("endDateTime") String endDateTime);

    @Query(value ="SELECT STAFF.STAFF_NAME AS \"name\",  ORGAN.NAME AS \"dept\",  STAFF.STAFF_NO AS \"staffNo\",  ALOG.OPEN_TIME AS \"openTime\" FROM  T_ACCESS_LOG ALOG  LEFT JOIN T_STAFF STAFF ON ALOG.ACCESS_CARD_NO = staff.STAFF_NO  LEFT JOIN T_ORGAN ORGAN on STAFF.ORGAN_ID = ORGAN.id WHERE ALOG.ACCESS_CARD_NO = STAFF.STAFF_NO AND ALOG.STAFF_NAME = STAFF.STAFF_NAME AND (ALOG.OWNER_ID = 72324) AND ALOG.OPEN_TIME BETWEEN TO_DATE (   :startDateTime,  'yyyy-mm-dd hh24:mi:ss' ) AND TO_DATE (  :endDateTime,  'yyyy-mm-dd hh24:mi:ss' ) AND TO_CHAR(ALOG.OPEN_TIME, 'hh24:mi:ss') BETWEEN '10:30:00' AND  '14:00:00' ORDER BY   ALOG.OPEN_TIME ASC",nativeQuery = true)
    public List<Map<String,Object>> lunchMealTimesDetail(@Param("startDateTime") String startDateTime, @Param("endDateTime") String endDateTime);

    @Query(value = " SELECT 	TEMP.day AS \"day\", 	count(* ) AS \"count\"  FROM 	( 	SELECT 		STAFF.STAFF_NAME, 		ORGAN.NAME, 		TO_CHAR( ALOG.OPEN_TIME, 'yyyy-mm-dd' ) AS day 		 	FROM 		T_ACCESS_LOG ALOG 		LEFT JOIN T_STAFF STAFF ON ALOG.ACCESS_CARD_NO = staff.STAFF_NO 		LEFT JOIN T_ORGAN ORGAN on STAFF.ORGAN_ID = ORGAN.id 	WHERE 		ALOG.ACCESS_CARD_NO = STAFF.STAFF_NO  		AND ALOG.STAFF_NAME = STAFF.STAFF_NAME 		AND ALOG.OWNER_ID = '72324'  		AND ALOG.OPEN_TIME BETWEEN TO_DATE( :startDateTime, 'yyyy-mm-dd hh24:mi:ss' )  	AND TO_DATE( :endDateTime, 'yyyy-mm-dd hh24:mi:ss' )  		AND TO_CHAR( ALOG.OPEN_TIME, 'hh24:mi:ss' ) BETWEEN '10:30:00'  		AND '14:00:00'  	GROUP BY 		STAFF.STAFF_NAME, 		ORGAN.NAME, 		TO_CHAR( ALOG.OPEN_TIME, 'yyyy-mm-dd' ) 	) TEMP  GROUP BY TEMP.day ORDER BY TEMP.day ASC",nativeQuery = true)
    public List<Map<String,Object>> lunchMealTimesByDay(@Param("startDateTime") String startDateTime, @Param("endDateTime") String endDateTime);

    @Query(value = " SELECT 	TEMP.\"NAME\" AS \"dept\" , 	TEMP.STAFF_NAME AS \"name\", 	count( * ) AS \"count\"  FROM 	( 	SELECT 		STAFF.STAFF_NAME, 		ORGAN.NAME, 		TO_CHAR( ALOG.OPEN_TIME, 'yyyy-mm-dd' )  	FROM 		T_ACCESS_LOG ALOG 		LEFT JOIN T_STAFF STAFF ON ALOG.ACCESS_CARD_NO = staff.STAFF_NO 		LEFT JOIN T_ORGAN ORGAN on STAFF.ORGAN_ID = ORGAN.id 	WHERE 		ALOG.ACCESS_CARD_NO = STAFF.STAFF_NO 		AND ALOG.STAFF_NAME = STAFF.STAFF_NAME 		AND ALOG.OWNER_ID = '72324'  		AND ALOG.OPEN_TIME BETWEEN TO_DATE( :startDateTime, 'yyyy-mm-dd hh24:mi:ss' )  		AND TO_DATE(:endDateTime, 'yyyy-mm-dd hh24:mi:ss' )  		AND TO_CHAR( ALOG.OPEN_TIME, 'hh24:mi:ss' ) BETWEEN '17:30:00'  		AND '21:00:00'  	GROUP BY 		STAFF.STAFF_NAME, 		ORGAN.NAME, 		TO_CHAR( ALOG.OPEN_TIME, 'yyyy-mm-dd' ) 	) TEMP  GROUP BY TEMP.STAFF_NAME, TEMP.\"NAME\"",nativeQuery = true)
    public List<Map<String,Object>> dinnerMealTimesByCount(@Param("startDateTime") String startDateTime, @Param("endDateTime") String endDateTime);

    @Query(value = " SELECT 	TEMP.day AS \"day\", 	count(* ) AS \"count\"  FROM 	( 	SELECT 		STAFF.STAFF_NAME, 		ORGAN.NAME, 		TO_CHAR( ALOG.OPEN_TIME, 'yyyy-mm-dd' ) AS day 		 	FROM 		T_ACCESS_LOG ALOG 		LEFT JOIN T_STAFF STAFF ON ALOG.ACCESS_CARD_NO = staff.STAFF_NO 		LEFT JOIN T_ORGAN ORGAN on STAFF.ORGAN_ID = ORGAN.id 	WHERE 		ALOG.ACCESS_CARD_NO = STAFF.STAFF_NO  		AND ALOG.STAFF_NAME = STAFF.STAFF_NAME 		AND ALOG.OWNER_ID = '72324'  		AND ALOG.OPEN_TIME BETWEEN TO_DATE( :startDateTime, 'yyyy-mm-dd hh24:mi:ss' )  	AND TO_DATE(:endDateTime, 'yyyy-mm-dd hh24:mi:ss' )  		AND TO_CHAR( ALOG.OPEN_TIME, 'hh24:mi:ss' ) BETWEEN '17:30:00'  		AND '21:00:00'  	GROUP BY 		STAFF.STAFF_NAME, 		ORGAN.NAME, 		TO_CHAR( ALOG.OPEN_TIME, 'yyyy-mm-dd' ) 	) TEMP  GROUP BY TEMP.day ORDER BY TEMP.day ASC",nativeQuery = true)
    public List<Map<String,Object>> dinnerMealTimesByDay(@Param("startDateTime") String startDateTime, @Param("endDateTime") String endDateTime);

    @Query(value = " SELECT   STAFF.STAFF_NAME AS \"name\",  ORGAN.NAME AS \"dept\",  STAFF.STAFF_NO AS \"staffNo\",  ALOG.OPEN_TIME AS \"openTime\"  FROM  T_ACCESS_LOG ALOG  LEFT JOIN T_STAFF STAFF ON ALOG.ACCESS_CARD_NO = staff.STAFF_NO  LEFT JOIN T_ORGAN ORGAN on STAFF.ORGAN_ID = ORGAN.id WHERE ALOG.ACCESS_CARD_NO = STAFF.STAFF_NO  AND ALOG.STAFF_NAME = STAFF.STAFF_NAME AND (ALOG.OWNER_ID = 72324) AND ALOG.OPEN_TIME BETWEEN TO_DATE (:startDateTime,  'yyyy-mm-dd hh24:mi:ss' ) AND TO_DATE (  :endDateTime,  'yyyy-mm-dd hh24:mi:ss' ) AND TO_CHAR(ALOG.OPEN_TIME, 'hh24:mi:ss') BETWEEN '17:30:00' AND '21:00:00'  ORDER BY   ALOG.OPEN_TIME ASC",nativeQuery = true)
    public List<Map<String,Object>> dinnerMealTimesDetail(@Param("startDateTime") String startDateTime, @Param("endDateTime") String endDateTime);

<think>嗯,用户想知道如何在Spring Boot使用JPA和MySQL时,在查询的时候直接把结果转成自定义的DTO类,而不是返回实体PO类。这个问题其实挺常见的,因为有时候我们不想暴露实体类的所有字段,或者需要组合多个表的数据。 首先,我得回忆一下JPA的处理方式。通常,JPA的Repository接口返回的是实体对象,这些对象映射到数据库表。但用户想要的是DTO,这意味着需要将查询结果投影到不同的类上。那应该怎么做呢? 可能的方法有几个。一种是使用JPQL或者HQL,通过构造函数表达式来实例化DTO。比如在JPQL中写SELECT new com.example.dto.MyDTO(a.name, a.age) FROM EntityA a,这样查询结果就会自动映射到DTO的构造函数里。不过这样的话,DTO必须有一个对应的构造函数,参数顺序和类型都要匹配。 另一种方法使用接口投影,也就是Spring Data JPA的接口投影功能。可以定义一个接口,里面包含要返回的属性的getter方法,然后在Repository的方法返回这个接口类型。这样JPA会自动生成代理类来实现这个接口,填充数据。不过这种方法可能不够灵活,特别是当DTO需要包含一些业务逻辑的时候。 还有,使用@Query注解结合自定义的SQL查询,可能也是一个途径。比如用原生SQL,然后通过ResultTransformer或者ResultSetMapping来转换结果到DTO。不过这种方法可能比较复杂,尤其是处理结果集映射的时候。 另外,JPA 2.2之后支持了ResultTransformer,不过Hibernate可能在之后的版本中弃用了这个。所以可能需要使用Tuple或者Object数组,再手动转换成DTO。但这样代码会比较繁琐,每个查询都要处理转换。 或者,可以使用Spring Data JPA的Projections,结合类基础的DTO。比如定义一个类,有对应的构造方法或者setter方法,然后在Repository方法返回这个类的列表。这样可能更灵活一些,特别是当需要处理多个不同字段的时候。 还需要考虑性能问题。如果直接返回实体,可能会有不必要的字段被加载,特别是关联关系。使用DTO可以只选择需要的字段,减少数据传输量,提高效率。 可能用户还不太清楚这些方法的具体实现步骤,所以需要详细说明每个方法的步骤,包括代码示例。比如,构造函数表达式需要DTO有全参构造,然后在JPQL中写new语句。接口投影则要定义接口,然后在Repository方法使用。还有,使用@Query配合原生SQL,可能需要定义结果集的映射关系。 另外,要提醒用户注意DTO的包路径,确保在JPQL中正确引用。还有,处理复杂查询时,可能需要连接多个表,这时候使用构造函数表达式或者接口投影是否能满足需求,或者是否需要使用其他方法。 可能用户遇到的另一个问题是,如何动态地构建DTO,比如根据不同条件返回不同字段。这时候可能需要更灵活的方式,比如使用QueryDSL或者JPA Criteria API来动态构造查询,再映射到DTO。 总结下来,应该分步骤介绍几种常用方法,比较它们的优缺点,给出示例代码,帮助用户选择适合自己场景的方式。同时,要确保语法正确,比如在JPQL中正确使用构造函数表达式,或者在接口投影中正确定义方法。</think>在Spring Boot中通过JPA查询时直接返回DTO类而非PO类,可以通过以下4种主流方案实现: 一、JPQL构造函数表达式(推荐方案) ```java // 1.定义DTO类(必须包含全参构造) public record UserDto(String username, String email) {} // 2.Repository层定义查询方法 public interface UserRepository extends JpaRepository<User, Long> { @Query("SELECT NEW com.example.dto.UserDto(u.username, u.email) " + "FROM User u WHERE u.status = 'ACTIVE'") List<UserDto> findActiveUsersAsDto(); } ``` ✅ 优势:类型安全,编译时检查 ❌ 限制:需要全参构造,字段多时代码量大 二、Spring Data投影接口 ```java // 1.定义投影接口 public interface UserProjection { String getUsername(); String getEmail(); } // 2.Repository使用接口返回 public interface UserRepository extends JpaRepository<User, Long> { List<UserProjection> findByDepartment(String department); } ``` ✅ 优势:无需实现类,自动生成代理 ❌ 限制:仅适合简单字段映射 三、ResultTransformer(Hibernate特有) ```java @PersistenceContext private EntityManager em; public List<UserDto> customQuery() { return em.createQuery( "SELECT u.username as username, u.email as email FROM User u") .unwrap(org.hibernate.query.Query.class) .setResultTransformer(Transformers.aliasToBean(UserDto.class)) .getResultList(); } ``` ✅ 优势:支持复杂结果映射 ❌ 限制:依赖Hibernate实现 四、Native SQL + ResultSetMapping ```java // 1.定义SqlResultSetMapping @SqlResultSetMapping( name = "UserDtoMapping", classes = @ConstructorResult( targetClass = UserDto.class, columns = { @ColumnResult(name = "username", type = String.class), @ColumnResult(name = "email", type = String.class) })) // 2.Repository使用原生查询 @Query(value = "SELECT username, email FROM users", nativeQuery = true) List<UserDto> findNativeAsDto(); ``` ✅ 优势:适合复杂SQL优化场景 ❌ 限制:需要维护结果集映射 性能优化建议: 1. 优先选择构造函数表达式(方案一),执行效率最高 2. 避免使用SELECT *,明确指定需要的字段 3. 复杂查询建议配合Pageable分页 4. N+1问题使用@EntityGraph解决 实际开发中推荐组合使用: - 简单查询 → 方案一/二 - 复杂SQL → 方案四 - 动态字段 → 方案三 - 分页场景 → 配合Page<UserDto> 完整示例(方案一): ```java // DTO public class UserDetailDto { private String username; private String departmentName; public UserDetailDto(String username, String departmentName) { this.username = username; this.departmentName = departmentName; } } // Repository public interface UserRepository extends JpaRepository<User, Long> { @Query("SELECT NEW com.example.dto.UserDetailDto(u.username, d.name) " + "FROM User u JOIN u.department d " + "WHERE u.createTime > :startDate") List<UserDetailDto> findRecentUsers(@Param("startDate") LocalDateTime startDate); } ``` 注意事项: 1. DTO必须与查询字段顺序严格一致 2. 包路径要完整(NEW全限定类名) 3. 聚合函数需要别名匹配 4. 建议配合Lombok @Data/@AllArgsConstructor简化代码 通过以上方案,可以在数据库查询阶段直接完成PO到DTO的转换,避免在内存中进行数据转换带来的性能损耗,同时保持代码的清晰度和可维护性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值