Spring-Data-Jpa projection用法

进行数据查询时,有时候并不需要把全部字段查询出来,只要查询部分的字段即可。那么就需要使用到Sping-Data-Jpa中的projection功能了。

前提:有用户表和订单表,用户与订单的关系是1对多关系。订单表的模型bean:

@Entity
@Table(name = "t_order")
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne(targetEntity = User.class)
    @JoinColumn(name = "user_id")
    private User user;

    private String orderName;
    private String orderNumber;

    @Convert(converter = DateToDateTimeConverter.class)
    private DateTime createTime;
    @Convert(converter = DateToDateTimeConverter.class)
    private DateTime updateTime;
    get/set方法略...
}

1、使用接口定义需要获取的字段,如获取订单名称和对应的用户id和用户名称,定义好需要获取的字段对应的get方法:

public interface OrderQueryDTO {

    public Long getUserId();

    public String getOrderName();

    public String getUsername();

}
db查询:
    @Query("select  orderName , user.userId ,user.username  from Order where id = ?1")
    <T> T findOrderWithUserNameByOrderId(Long id, Class<T> target);

使用:

    OrderQueryDTO order2 = orderReadRepository.findOrderWithUserNameByOrderId(1L, OrderQueryDTO.class);
        log.info("2=====使用接口作为projection===" + order2 + "," + order2.getClass().getName());

执行后对应的log:

select order0_.order_name as col_0_0_, order0_.user_id as col_1_0_, user1_.username as col_2_0_ from t_order order0_, t_user user1_ where order0_.user_id=user1_.user_id and order0_.id=?
 2=====使用接口作为projection==={userId=1, orderName=orderName, username=user0},com.sun.proxy.$Proxy105

2、使用Bean作为DTO,如只需要查询订单名称字段,则定义如下bean,注意需要使用构造方法。

public class OrderQueryDTO2 {

    private String orderName;

    public OrderQueryDTO2(String orderName) {
        super();
        this.orderName = orderName;
    }
    get/set方法
    }

    db方法定义:
    OrderQueryDTO2 findOrderNameById(Long id);

使用:

    OrderQueryDTO2 order5 = orderReadRepository.findOrderNameById(1L);
        log.info("5=====findOrderNameById 跟方法名无关,而是根据返回的bean的字段来的===" + order5.getOrderName());

查询结果:

Hibernate: select order0_.order_name as col_0_0_ from t_order order0_ where order0_.id=?
5=====findOrderNameById 跟方法名无关,而是根据返回的bean的字段来的===orderName

根据sql可以看出只查询了订单名称这一个字段

3、查询单个字段,如查询用户id,需要使用@Query设置sql

/**
     * 自定义查询字段,注意这里查询使用的是bean对应的属性字段而不是数据库字段
     * @param username
     * @return
     */
    @Query("select userId from User where username = ?1")
    Long findUserIdByUsername(String username);

以上代码已提交至git服务器:
[oschina 地址]
http://git.oschina.net/cmlbeliever/SpringBootLearning
[github 地址]
https://github.com/cmlbeliever/SpringBootLearning
中SpringJpa工程。对应的类路径为测试包下的com.cml.learn.jpa.test.order.OrderQueryTest


总结:projection方式有如下三种

  1. 使用构造方法进行设置的bean
  2. 使用接口定义,自定义get方法
  3. 自定义sql,返回需要的字段
Spring Data JPA 中,我们可以通过定义 Repository 接口中的方法,使用方法名来自动生成查询语句。但是有时候,我们需要自定义查询结果,比如说只需要查询结果中的部分字段,或者对查询结果进行聚合操作等。这时,我们可以使用 Spring Data JPA 提供的投影(Projection)功能来自定义查询结果。 投影是指将实体类中的一部分属性或关联属性映射成一个接口或类,从而返回一个自定义的结果集。Spring Data JPA 支持三种投影方式: 1. 接口投影:定义一个接口,接口中声明需要的属性,Spring Data JPA 将根据接口定义的属性生成查询结果。 2. 类投影:定义一个类,类中声明需要的属性,Spring Data JPA 将根据类定义的属性生成查询结果。 3. 动态投影:可以根据查询条件动态地返回不同的投影结果,比如说根据用户的角色返回不同的查询结果。 下面是一个简单的例子,演示如何使用接口投影来自定义查询结果: 定义一个接口投影: ```java public interface UserProjection { String getUsername(); String getEmail(); } ``` 在 UserRepository 中使用接口投影: ```java public interface UserRepository extends JpaRepository<User, Long> { List<UserProjection> findByUsername(String username); } ``` 通过上面的代码,我们可以在 UserRepository 中定义一个方法 findByUsername,该方法会返回一个 List<UserProjection> 类型的结果集,该结果集中只包含 username 和 email 两个字段。 当我们调用 findByUsername 方法时,Spring Data JPA 将根据方法名自动生成查询语句,并根据 UserProjection 接口中定义的属性生成查询结果。 当然,除了接口投影,还有其他的投影方式,你可以根据自己的需求选择适合的方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值