我正在使用Spring Boot 2.x,Spring Data REST,Spring HATEOAS,Spring JPA,Hibernate。 我知道this question,但是它已经很老了,我想详细说明一下我的情况。
我有两个像这样的简单豆子:
@Entity
@Data
public class Contact extends AbstractEntity {
private String sid;
private String firstName;
private String lastName;
private String companyName;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "store_id", updatable = false)
private Store store;
//more custom fields
}
和:
@Entity
@Data
public class Store extends AbstractEntity {
private String code;
private String name;
private String sid;
//more custom fields
}
我正在通过REST公开存储库:
@Transactional
@PreAuthorize("isAuthenticated()")
public interface ContactRepository extends JpaRepository<Contact, Long> {
}
和
@Transactional
@PreAuthorize("isAuthenticated()")
public interface StoreRepository extends JpaRepository<Store, Long>, StoreCustomRepository<Store, Long> {
}
如果我致电http://localhost:8082/api/v1/contacts/1,我会得到:
{
"sid": "962732c2-68a8-413b-9762-f676d42046b4",
"createdBy": "1ccf2329-4aa3-4d55-8878-25517edf1522",
"createdDate": "2019-05-28T14:06:07.011Z",
"lastModifiedDate": "2019-06-04T08:46:02.591Z",
"lastModifiedBy": "system",
"createdByName": "Agent",
"lastModifiedByName": null,
"type": "CUSTOMER",
"personType": "NATURAL_PERSON",
"firstName": "Daniele",
"lastName": "LastName",
"companyName": null,
"fullName": "Full name",
"gender": "MALE",
"birthDate": "2019-05-21T00:00:00Z",
"birthCity": null,
"job": null,
"billingAddress": "Via 123",
"billingZipCode": "14018",
"billingCity": "Roatto",
"billingDistrict": "AT",
"billingCountry": "IT",
"shippingAddress": "Via 123",
"shippingZipCode": "14018",
"shippingCity": "Roatto",
"shippingDistrict": "AT",
"shippingCountry": "IT",
"taxCode": "",
"vatNumber": null,
"landlinePhone": null,
"mobilePhone": null,
"fax": null,
"email": "aaa@sdfg.it",
"certifiedEmail": null,
"survey": null,
"iban": null,
"swift": null,
"publicAdministration": false,
"sdiAccountId": "0000000",
"preset": false,
"_links": {
"self": {
"href": "http://localhost:8082/api/v1/contacts/1"
},
"contact": {
"href": "http://localhost:8082/api/v1/contacts/1{?projection}",
"templated": true
},
"notes": {
"href": "http://localhost:8082/api/v1/contacts/1/notes"
},
"auditLogs": {
"href": "http://localhost:8082/api/v1/contacts/1/auditLogs"
},
"media": {
"href": "http://localhost:8082/api/v1/contacts/1/media"
},
"privacyAgreements": {
"href": "http://localhost:8082/api/v1/contacts/1/privacyAgreements"
},
"eyeExams": {
"href": "http://localhost:8082/api/v1/contacts/1/eyeExams"
},
"contactLensEyeTests": {
"href": "http://localhost:8082/api/v1/contacts/1/contactLensEyeTests"
},
"eyeExamsCount": {
"href": "http://localhost:8082/api/v1/contacts/1/eyeExams/count"
},
"documents": {
"href": "http://localhost:8082/api/v1/contacts/1/documents"
},
"pendingSalesOrders": {
"href": "http://localhost:8082/api/v1/contacts/1/pendingSalesOrders"
},
"latestPurchasedFrames": {
"href": "http://localhost:8082/api/v1/contacts/1/latestPurchasedFrames"
},
"latestPurchasedItems": {
"href": "http://localhost:8082/api/v1/contacts/1/latestPurchasedItems"
},
"latestSoldItems": {
"href": "http://localhost:8082/api/v1/contacts/1/latestSoldItems"
},
"latestDocuments": {
"href": "http://localhost:8082/api/v1/contacts/1/latestDocuments"
},
"store": {
"href": "http://localhost:8082/api/v1/contacts/1/store{?projection}",
"templated": true
}
}
}
如Spring Data REST文档所述,如果有相关资源(存储)的存储库,它将显示为链接,并且未嵌入。
我还使用https://github.com/bohnman/squiggly-java来动态选择字段。最终目标是调用联系人端点,仅选择很少的联系人字段,并使嵌套商店仅包含代码和自我链接。
所以我想收到这样的答复:
{
"store": {
"code": "RO",
"_links": {
"self": {
"href": "http://localhost:8082/api/v1/stores/1{?projection}",
"templated": true
}
}
},
"lastName": "LastName",
"_links": {
"self": {
"href": "http://localhost:8082/api/v1/contacts/1"
},
"contact": {
"href": "http://localhost:8082/api/v1/contacts/1{?projection}",
"templated": true
},
"store": {
"href": "http://localhost:8082/api/v1/contacts/1/store{?projection}",
"templated": true
}
}
}
要拥有嵌入式嵌套资源,我必须创建一个投影:
@Projection(名称=“内联”,类型= {Contact.class}) 公共接口ContactInlineProjection {
String getFirstName();
String getLastName();
Store getStore();
//All other fields
}
但是结果没有嵌套资源的链接:
{
"store": {
"code": "RO"
},
"lastName": "LastName",
"_links": {
"self": {
"href": "http://localhost:8082/api/v1/contacts/1"
},
"contact": {
"href": "http://localhost:8082/api/v1/contacts/1{?projection}",
"templated": true
},
"store": {
"href": "http://localhost:8082/api/v1/contacts/1/store{?projection}",
"templated": true
}
}
}
为了使其工作,我还必须为Store创建一个投影:
@Projection(name = "inline", types = {Store.class})
public interface StoreLightProjection {
String getName();
String getCode();
//other fields
}
,然后将“联系人投影”更改为:
@Projection(name = "inline", types = {Contact.class})
public interface ContactInlineProjection {
String getFirstName();
String getLastName();
StoreLightProjection getStore();
}
这样做,回复看起来就像我想要的。这是正常现象还是潜在的错误?有没有其他方法可以用更少的代码来实现目标?