增强 Spring 数据 Rest 传递空关系
Enhanced Spring Data Rest delivers empty relations
在我当前使用 Spring-Boot、-HATEOAS、-Rest-Data 的实现中,我试图节省一些进一步的休息调用并增强我的休息资源以获取积分,以提供积分关系(请参阅下面的帐户作为 ManyToOne 和 creditBookingClassPayments 作为 OneToMany)。
现在的问题是我无法得到它运行。调用总是传递空关系。我真的很感激这方面的帮助。
周边环境如下:
Credit.java
@Entity
@Getter
@Setter
public class Credit {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Setter(NONE)
@Column(name = "id")
private Long itemId;
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="account_id", nullable = false)
private Account account;
@OneToMany(mappedBy = "credit")
private List<CreditBookingClassPayment> creditBookingClassPayments = new ArrayList<>();
@NotNull(message="Please enter a valid short name.")
@Column(length = 10, nullable = false)
private String shortName;
@NotNull(message="Please enter a valid name.")
@Column(nullable = false)
private String name;
...
}
CreditRepositoryCustomImpl.java
使用QueryDsl实现增强信用资源
...
@Override
public List<Credit> findDistinctByAccountItemIdNew(Long accountId) {
QCredit credit = QCredit.credit;
QAccount account = QAccount.account;
QCreditBookingClassPayment creditBookingClassPayment = QCreditBookingClassPayment.creditBookingClassPayment;
QBookingClass bookingClass = QBookingClass.bookingClass;
BooleanExpression hasAccountItemId = credit.account.itemId.eq(accountId);
List<Credit> credits = from(credit).where(hasAccountItemId)
.innerJoin(credit.account, account)
.leftJoin(credit.creditBookingClassPayments, creditBookingClassPayment)
.leftJoin(creditBookingClassPayment.bookingClass, bookingClass).groupBy(credit.itemId).fetch();
return credits;
}
...
CreditController.java
查看此处的 responseBody 所有(帐户和信用支付)都可用于信用
@RepositoryRestController
public class CreditController {
@Autowired
private CreditRepository creditRepository;
@RequestMapping(value = "/credit/search/findAllByAccountItemIdNew", method= RequestMethod.GET, produces = MediaTypes.HAL_JSON_VALUE)
@ResponseBody
public ResponseEntity<Resources<PersistentEntityResource>> findAllByAccountItemIdNew(@RequestParam Long accountId, PersistentEntityResourceAssembler persistentEntityResourceAssembler) {
List<Credit> credits = creditRepository.findDistinctByAccountItemIdNew(accountId);
Resources<PersistentEntityResource> responseBody = new Resources<PersistentEntityResource>(credits.stream()
.map(persistentEntityResourceAssembler::toResource)
.collect(Collectors.toList()));
return ResponseEntity.ok(responseBody);
}
}
CreditResourceIntegrTest.java
此处 creditResourcesEntity 持有信用,但帐户为空,creditBookingClassPayment 为空数组
@Test
public void testFindAllByAccountItemId() throws URISyntaxException {
URIBuilder builder = new URIBuilder(creditFindAllByAccountItemIdRestUrl);
builder.addParameter("accountId", String.valueOf(EXPECTED_ACCOUNT_ID));
builder.addParameter("projection", "base");
RequestEntity<Void> request = RequestEntity.get(builder.build())
.accept(MediaTypes.HAL_JSON).acceptCharset(Charset.forName("UTF-8")).build();
ResponseEntity<Resources<Resource<Credit>>> creditResourcesEntity =
restTemplate.exchange(request, new ParameterizedTypeReference<Resources<Resource<Credit>>>() {});
assertEquals(HttpStatus.OK, creditResourcesEntity.getStatusCode());
//assertEquals(EXPECTED_CREDIT_COUNT, creditResourcesEntity.getBody().getContent().size());
}
我错过了什么吗?
感谢您的帮助!
卡斯滕
好的,PersistentEntityResourceAssembler 不支持关系。但这可以通过使用投影来处理。
CreditProjection.java
@Projection(name = "base" , types = Credit.class)
public interface CreditProjection {
String getShortName();
String getName();
List<CreditBookingClassPaymentProjection> getCreditBookingClassPayments();
BigDecimal getValue();
BigDecimal getInterestRate();
BigDecimal getMonthlyRate();
}
CreditBookingClassPaymentProjection.java
@Projection(name = "base" , types = CreditBookingClassPayment.class)
public interface CreditBookingClassPaymentProjection {
BookingClass getBookingClass();
CreditPaymentType getCreditPaymentType();
}
CreditController.java
@RepositoryRestController
public class CreditController {
@Autowired
private ProjectionFactory projectionFactory;
@Autowired
private CreditRepository creditRepository;
@RequestMapping(value = "/credit/search/findAllByAccountItemIdNew", method = RequestMethod.GET, produces = MediaTypes.HAL_JSON_VALUE)
@ResponseBody
public ResponseEntity<Resources<?>> findAllByAccountItemIdNew(@RequestParam Long accountId,
PersistentEntityResourceAssembler persistentEntityResourceAssembler) {
List<Credit> credits = creditRepository.findDistinctByAccountItemIdNew(accountId);
List<PersistentEntityResource> creditResources = new ArrayList<>();
for (Credit credit : credits) {
// credit.getCreditBookingClassPayments()
PersistentEntityResource creditResource = persistentEntityResourceAssembler.toResource(credit);
creditResources.add(creditResource);
}
Resources<CreditProjection> responseBody = new Resources<CreditProjection>(credits.stream()
.map(credit -> projectionFactory.createProjection(CreditProjection.class, credit))
.collect(Collectors.toList()));
return ResponseEntity.ok(responseBody);
}
}
在我当前使用 Spring-Boot、-HATEOAS、-Rest-Data 的实现中,我试图节省一些进一步的休息调用并增强我的休息资源以获取积分,以提供积分关系(请参阅下面的帐户作为 ManyToOne 和 creditBookingClassPayments 作为 OneToMany)。 现在的问题是我无法得到它运行。调用总是传递空关系。我真的很感激这方面的帮助。
周边环境如下:
Credit.java
@Entity
@Getter
@Setter
public class Credit {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Setter(NONE)
@Column(name = "id")
private Long itemId;
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="account_id", nullable = false)
private Account account;
@OneToMany(mappedBy = "credit")
private List<CreditBookingClassPayment> creditBookingClassPayments = new ArrayList<>();
@NotNull(message="Please enter a valid short name.")
@Column(length = 10, nullable = false)
private String shortName;
@NotNull(message="Please enter a valid name.")
@Column(nullable = false)
private String name;
...
}
CreditRepositoryCustomImpl.java
使用QueryDsl实现增强信用资源
...
@Override
public List<Credit> findDistinctByAccountItemIdNew(Long accountId) {
QCredit credit = QCredit.credit;
QAccount account = QAccount.account;
QCreditBookingClassPayment creditBookingClassPayment = QCreditBookingClassPayment.creditBookingClassPayment;
QBookingClass bookingClass = QBookingClass.bookingClass;
BooleanExpression hasAccountItemId = credit.account.itemId.eq(accountId);
List<Credit> credits = from(credit).where(hasAccountItemId)
.innerJoin(credit.account, account)
.leftJoin(credit.creditBookingClassPayments, creditBookingClassPayment)
.leftJoin(creditBookingClassPayment.bookingClass, bookingClass).groupBy(credit.itemId).fetch();
return credits;
}
...
CreditController.java
查看此处的 responseBody 所有(帐户和信用支付)都可用于信用
@RepositoryRestController
public class CreditController {
@Autowired
private CreditRepository creditRepository;
@RequestMapping(value = "/credit/search/findAllByAccountItemIdNew", method= RequestMethod.GET, produces = MediaTypes.HAL_JSON_VALUE)
@ResponseBody
public ResponseEntity<Resources<PersistentEntityResource>> findAllByAccountItemIdNew(@RequestParam Long accountId, PersistentEntityResourceAssembler persistentEntityResourceAssembler) {
List<Credit> credits = creditRepository.findDistinctByAccountItemIdNew(accountId);
Resources<PersistentEntityResource> responseBody = new Resources<PersistentEntityResource>(credits.stream()
.map(persistentEntityResourceAssembler::toResource)
.collect(Collectors.toList()));
return ResponseEntity.ok(responseBody);
}
}
CreditResourceIntegrTest.java
此处 creditResourcesEntity 持有信用,但帐户为空,creditBookingClassPayment 为空数组
@Test
public void testFindAllByAccountItemId() throws URISyntaxException {
URIBuilder builder = new URIBuilder(creditFindAllByAccountItemIdRestUrl);
builder.addParameter("accountId", String.valueOf(EXPECTED_ACCOUNT_ID));
builder.addParameter("projection", "base");
RequestEntity<Void> request = RequestEntity.get(builder.build())
.accept(MediaTypes.HAL_JSON).acceptCharset(Charset.forName("UTF-8")).build();
ResponseEntity<Resources<Resource<Credit>>> creditResourcesEntity =
restTemplate.exchange(request, new ParameterizedTypeReference<Resources<Resource<Credit>>>() {});
assertEquals(HttpStatus.OK, creditResourcesEntity.getStatusCode());
//assertEquals(EXPECTED_CREDIT_COUNT, creditResourcesEntity.getBody().getContent().size());
}
我错过了什么吗?
感谢您的帮助! 卡斯滕
好的,PersistentEntityResourceAssembler 不支持关系。但这可以通过使用投影来处理。
CreditProjection.java
@Projection(name = "base" , types = Credit.class)
public interface CreditProjection {
String getShortName();
String getName();
List<CreditBookingClassPaymentProjection> getCreditBookingClassPayments();
BigDecimal getValue();
BigDecimal getInterestRate();
BigDecimal getMonthlyRate();
}
CreditBookingClassPaymentProjection.java
@Projection(name = "base" , types = CreditBookingClassPayment.class)
public interface CreditBookingClassPaymentProjection {
BookingClass getBookingClass();
CreditPaymentType getCreditPaymentType();
}
CreditController.java
@RepositoryRestController
public class CreditController {
@Autowired
private ProjectionFactory projectionFactory;
@Autowired
private CreditRepository creditRepository;
@RequestMapping(value = "/credit/search/findAllByAccountItemIdNew", method = RequestMethod.GET, produces = MediaTypes.HAL_JSON_VALUE)
@ResponseBody
public ResponseEntity<Resources<?>> findAllByAccountItemIdNew(@RequestParam Long accountId,
PersistentEntityResourceAssembler persistentEntityResourceAssembler) {
List<Credit> credits = creditRepository.findDistinctByAccountItemIdNew(accountId);
List<PersistentEntityResource> creditResources = new ArrayList<>();
for (Credit credit : credits) {
// credit.getCreditBookingClassPayments()
PersistentEntityResource creditResource = persistentEntityResourceAssembler.toResource(credit);
creditResources.add(creditResource);
}
Resources<CreditProjection> responseBody = new Resources<CreditProjection>(credits.stream()
.map(credit -> projectionFactory.createProjection(CreditProjection.class, credit))
.collect(Collectors.toList()));
return ResponseEntity.ok(responseBody);
}
}