Java Spring 投影内投影

Java Spring projection inside projection

是否可以使用投影并在一些相关对象中使用它自己的投影?

例如,一个有 Exam,那个有 List<Question>。我想请求一份考试列表(我有一个 @projection),但我想为每个相关 Question

定义要检索的属性

如果我理解正确的话,您想使用 Projection 作为 Projection 的子项。如果是这样,是的,你可以。您可以创建一个 QuestionProjection 并在 ExamProjection 中使用。

示例:

@Projection(name = "questionProjection", types = { Question.class }) 
public interface QuestionProjection {
    // Getters
}

@Projection(name = "examProjection", types = { Exam.class }) 
public interface ExamProjection {
    List<QuestionProjection> getQuestionList();

    // Other Getters
}

你可以这样做:

假设您的 Exam 实体可能是:

@Entity
@Table(name = "EXAM")
public class Exam implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID")
    private Long id;

    @Column(name = "DESCR")
    private String descr;

    @OneToMany(mappedBy = "exam")
    private List<Question> questions;

      // Getters and Setters

和您的 Question 实体

@Entity
@Table(name = "QUESTION")
public class Question implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID")
    private Long id;

    @Column(name = "DESCR")
    private String descr;

    @Column(name = "CONT")
    private String cont;

    @ManyToOne
    @JoinColumn(name = "EXAM_ID")
    @JsonIgnoreProperties("questions")
    private Exam exam;

所以,创建投影

public interface ExamProjection {
    Long getId();

    String getDescr();

    List<QuestionProjection> getQuestions();
}

public interface QuestionProjection {
    Long getId();

    String getDescr();
}

您的存储库

@Repository
public interface ExamRepository extends JpaRepository<Exam, Long> {

    List<Exam> findAll();

    @Query("SELECT e FROM Exam e")
    List<ExamProjection> findAllProjection();
}

观察到使用 findAll() 方法并将列表类型作为 ExamProjection 传递时,出于某种原因,会导致不兼容的 return 类型错误。为避免这种情况,请创建一个自定义方法,在本例中为 findAllProjection().

服务

@Service
public class ExamService {

    @Autowired
    ExamRepository examRepository;

    public List<ExamProjection> findAllProjection() {
        return examRepository.findAllProjection();
    }
}

最后,资源

@RestController
@RequestMapping(value = "/exam")
public class ExamResource {

    @Autowired
    ExamService examService;

    @GetMapping
    public ResponseEntity<List<ExamProjection>> findAll() {
        return ResponseEntity.ok().body(examService.findAllProjection());
    }
}

使用上面的方法,json returned 不包含字段 cont,因为 de QuestionProjection 没有方法 getCont().

[
    {
        "id": 1,
        "descr": "First Exam",
        "questions": [
            {
                "id": 1,
                "descr": "First Question"
            },
            {
                "id": 2,
                "descr": "Second Question"
            }
        ]
    }
]

如果 QuestionProjection 更改为

public interface QuestionProjection {
    Long getId();

    String getCont();
}

json returned 更改为

[
    {
        "id": 1,
        "descr": "First Exam",
        "questions": [
            {
                "id": 1,
                "cont": "First Question Content"
            },
            {
                "id": 2,
                "cont": "Second Question Content"
            }
        ]
    }
]