Spring JPA自定义查询结果的接收方式
一、标准使用方法
//构建实体类
@Getter
@Setter
@Entity
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Table(name = "user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private Integer age;
private String address;
}
//继承JPA
public interface UserRepository extends JpaRepository<User,Long> {
}
//调用测试
@RunWith(SpringRunner.class)
@SpringBootTest
class UserTest {
@Autowired
UserRepository userRepository;
@Test
void testUser() {
User newUser = User.builder()
.id(1L)
.username("zhangsan")
.age(18)
.address("北京市").build();
User savedUser = userRepository.save(newUser);
assertEquals("zhangsan",savedUser.getUsername());
}
}
如图所示,插入成功。

二、自定义查询结果的接收
假设我们不想查询user表中的所有字段,而只需要其中的几个字段作为前端输出。
当然,JPA给我们提供了自定义SQL的功能进行个性化的查询。使用@Query就可以自定义SQL语句,编写自定义的查询语句了。
但是,它的使用方式分为两种:
- 一种是特定JPQL语言,这是通过实体对象来查询属性,而不用考虑对应的表名称和字段名称。
- 一种是SQL语言,还是像原来一样操作对应的表和字段。
1.那么在UserRepository 中应该怎么写自定义查询语句呢?
//创建个性化的DTO用于接收
@Value
public class UserDTO {
Long id;
String username;
}
//写sql语句
public interface UserRepository extends JpaRepository<User,Long> {
//@Query("select u from User u where u.id =?1")
//是像这样,还是怎么写呢?
UserDTO findUserDTOByID(Long id);
}
//调用
@RunWith(SpringRunner.class)
@SpringBootTest
class UserTest {
@Autowired
UserRepository userRepository;
@Test
void testUserDTO() {
UserDTO dto = userRepository.findUserDTOByID(1L);
assertEquals("zhangsan",dto.getUsername());
}
}
可能的错误的查询方式:
//1.意图User实体自动映射某些属性到UserDTO
public interface UserRepository extends JpaRepository<User,Long> {
@Query("select u from User u where u.id =?1")
UserDTO findUserDTOByID(Long id);
//但是会报org.springframework.core.convert.ConverterNotFoundException错误
}
//2.意图挑出User的某些字段会自动映射到UserDTO
public interface UserRepository extends JpaRepository<User,Long> {
@Query("select u.id,u.username from User u where u.id =?1")
UserDTO findUserDTOByID(Long id);
//但是会报org.springframework.core.convert.ConverterNotFoundException错误
}
//3.意图挑出User的某些字段会自动映射到UserDTO
public interface UserDTORepository extends JpaRepository<UserDTO,Long> {
@Query("select u.id,u.username from User u where u.id =?1")
UserDTO findByID(Long id);
//但是这会生成一个新表
}
在上面虽然UserDTO只是User中的子集,只有它的两个属性,但是如果直接用UserDTO接收查询结构,就会报这种 类型转换错误。
这是因为UserRepository是实体对象User的仓库,必须用User来接收,不能用别的对象来接收。
那么我们能不能再创建一个UserDTORepository来接收查询结果呢?
这是不行的,因为UserDTORepository必须映射对应的表,才能查询UserDTO对象。而我们当然不希望又创建与User相似的表。
正确的查询方式:
//1.使用Object接收
public interface UserRepository extends JpaRepository<User,Long> {
@Query("select u.id,u.username from User u where u.id =?1")
Object findUserDTOByID(Long id);
//倒是能接收到结果,但是丢失了属性名称,必须数组的索引访问,不方便
}
//2.使用全限定名接收
public interface UserRepository extends JpaRepository<User,Long> {
@Query("select new com.example.admin.ums.domain.user.UserDTO(id,username) from User u where u.id =?1")
UserDTO findUserDTOByID(Long id);
//能接收到结果,但是UserDTO必须有构造函数,带上所有参数,也不方便
}
//3.定义接口来接收,使用的是projections接口投影机制
public interface IUser {
//定义这些getter方法才能接收结果
Long getId();
String getUsername();
}
//用接口接收查询结果
public interface UserRepository extends JpaRepository<User,Long> {
@Query("select u.id as id ,u.username as username from User u where u.id =?1")
IUser findUserDTOByID(Long id);
//能查询到结果,但是必须用接口接收,可能不习惯
}
//4.泛型动态查询投影
public interface UserRepository extends JpaRepository<User,Long> {
<T> T findById(Long id, Class<T> type);
//只需要输入ID和类类型就能查到结果,这个利用了方法名的查询生成器机制,不用专门写@Query
//同时使用动态查询投影,所以不用输入很多参数,方便了很多,强烈推荐
}
//5.用Map接收查询的结果
public interface UserRepository extends JpaRepository<User,Long> {
@Query("select u.id as id ,u.username as username, u.address as address from User u where u.id =?1")
Map<String,Object> findUserDTO(Long id);
//需要写JPQL语句,必须用as取别名,否则就没有key值
//优点是不用构造DTO直接输出给前端
//缺点是查出来的不是对象,不方便再处理业务逻辑,若参数很多,就会很繁琐
}
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
相关文章
Spring Security自定义登录页面认证过程常用配置
这篇文章主要为大家介绍了Spring Security自定义登录页面认证过程常用配置示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪2022-08-08
java web实现简单登录注册功能全过程(eclipse,mysql)
前期我们学习了javaweb项目用JDBC连接数据库,还有数据库的建表功能,下面这篇文章主要给大家介绍了关于java web实现简单登录注册功能的相关资料,需要的朋友可以参考下2022-07-07
Spring Boot集成Milvus快速入门demo示例详解
Milvus是一种高性能向量数据库,支持从笔记本到大型分布式系统的多环境运行,它以开源和云服务形式提供,是LFAI & Data Foundation的项目,采用Apache 2.0许可,Milvus特别支持高并行化和解耦的系统架构,使其能够随数据增长而扩展,支持各种复杂搜索功能,满足企业级AI应用需求2024-09-09
通过实例深入学习Java的Struts框架中的OGNL表达式使用
这篇文章主要通过实例介绍了Java的Strus框架中的OGNL表达式使用,Struts框架是Java的SSH三大web开发框架之一,需要的朋友可以参考下2015-11-11
java 集合工具类Collections及Comparable和Comparator排序详解
这篇文章主要介绍了java集合工具类Collections及Comparable和Comparator排序详解,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下2022-06-06


最新评论