How to not return an specific column using PagingA

2019-05-28 22:13发布

I know the title may sound a bit confusing, but I did not know how to summarize my problem on the title.

My main problem is that I do not want to return an specific column using PagingAndSortingRepository. Imagine the following scenario:

I have two entitys, one called Users:

@Entity
@Table(name = "users")
public class User implements Serializable {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;

  @NotBlank()
  @Column(name = "name")
  private String name;

  @Column(name = "password")
  private String password;

}

And one called Cars:

@Entity
@Table(name = "car")
public class Car implements Serializable {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;

  @NotBlank()
  @Column
  private String name;

  @ManyToOne(targetEntity = User.class, fetch = FetchType.EAGER, cascade = CascadeType.MERGE)
  @JoinColumn(name = "owner_id", referencedColumnName = "id")
  private User owner;

}

I want to return a list of car by user's name using PagingAndSortingRepository. Using the following interface I can achieve that:

public interface CarRepository extends PagingAndSortingRepository<Car, Long> {

  List<Car> findByOwner_name(String name);

}

However, with said interface the result will also return the user's password on it. I could use a for on each element of the list and set the password as null, but it would be troublesome in a scenario where there is a user with lots of cars. How could I make it so that the result of the list come with the specific column, password, without any value to the user?

Thanks in advance =).

ps: I thought about returning a list of projection instead of a list of Car, but I do not know how to say it to the projection that just one attribute from the class should be null.

3条回答
孤傲高冷的网名
2楼-- · 2019-05-28 22:54

Projections can be used recursively. Something like this should work:

interface CarPojection{

      Long getId();
      String getName();
      UserSummary getUser();

      interface UserSummary {
        Long getId();
        String getName();
      }
    }

And your repository should return CarPojection Find more information in Spring docs: https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections

查看更多
小情绪 Triste *
3楼-- · 2019-05-28 23:17

You can return a subset of data by providing a matching constructor in your entity class.

@Query("select new com.foo.bar.entity.User(u.id, u.name) from User u where u.name = ?1")
List<User> findByOwner_name(String name);

In you class User just provide the constructor and other properties will be left null:

public User(Long id, String name) {
    // ...       
}
查看更多
看我几分像从前
4楼-- · 2019-05-28 23:18

You need to use Projections for this purpose. It is documented in detail here

Create an interface with fields you want to include in the entity to be returned.
For example, in your case it would be like this

interface CarSummary {

  String getName();
  Long getId();
  UserSummary getUser();

  interface UserSummary {
    String getName();
    Long getId();
  }
}

and modify your repository like this

public interface CarRepository extends PagingAndSortingRepository<Car, Long> {
    Collection<CarSummary> findByOwner_name(String name);  
}
查看更多
登录 后发表回答