Ответ 1
Попробуйте использовать JsonIgnore с полями, которые вам не нужны в возвращаемом JSON
@JsonIgnore
private String stateDetails;
У меня есть таблица Country and State, для которой я интегрирован с Spring Data JPA. Я создал функцию public Page<CountryDetails> getAllCountryDetails
в моей CountryServiceImpl для получения всей страны и соответствующих данных о состоянии. Услуга работает нормально и дает мне следующий результат:
{
"content": [
{
"id": 123,
"countryName": "USA",
"countryCode": "USA",
"countryDetails": "XXXXXXXX",
"countryZone": "XXXXXXX",
"states": [
{
"id": 23,
"stateName": "Washington DC",
"countryCode": "USA",
"stateCode": "WAS",
"stateDetails": "XXXXX",
"stateZone": "YYYYYY"
},
{
"id": 24,
"stateName": "Some Other States",
"countryCode": "USA",
"stateCode": "SOS",
"stateDetails": "XXXXX",
"stateZone": "YYYYYY"
}
]
}
],
"last": false,
"totalPages": 28,
"totalElements": 326,
"size": 12,
"number": 0,
"sort": null,
"numberOfElements": 12,
"first": true
}
Мой полный код приведен ниже:
CountryRepository.java
@Repository
public interface CountryRepository extends JpaRepository<CountryDetails, Integer> {
@Query(value = "SELECT country FROM Country country GROUP BY country.countryId ORDER BY ?#{#pageable}",
countQuery = "SELECT COUNT(*) FROM Country country GROUP BY country.countryId ORDER BY ?#{#pageable}")
public Page<CountryDetails> findAll(Pageable pageRequest);
}
CountryServiceImpl.java
@Service
public class CountryServiceImpl implements CountryService {
@Autowired
private CountryRepository countryRepository;
@Override
public Page<CountryDetails> getAllCountryDetails(final int page, final int size) {
return countryRepository.findAll(new PageRequest(page, size));
}
}
CountryDetails.java
@Entity
@Table(name = "country", uniqueConstraints = @UniqueConstraint(columnNames = "id"))
public class CountryDetails {
@Id
@GeneratedValue
@Column(name = "id", unique = true, nullable = false)
private Integer id;
private String countryName;
private String countryCode;
private String countryDetails;
private String countryZone;
@JsonManagedReference
@OneToMany(fetch = FetchType.LAZY, mappedBy = "countryDetails")
private List<State> states;
// getters / setters omitted
}
State.java
@Entity
@Table(name = "state", uniqueConstraints = @UniqueConstraint(columnNames = "id"))
public class State {
@Id
@GeneratedValue
@Column(name = "id", unique = true, nullable = false)
private Integer id;
private String stateName;
private String countryCode;
private String stateCode;
private String stateDetails;
private String stateZone;
@JsonBackReference
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "countryCode", nullable = false, insertable = false, updatable = false, foreignKey = @javax.persistence.ForeignKey(name="none",value = ConstraintMode.NO_CONSTRAINT))
private CountryDetails countryDetails;
// getters / setters omitted
}
Фактически, что я хочу, чтобы служба страны возвращалась с минимальной информацией, как показано ниже
{
"content": [
{
"countryName": "USA",
"countryCode": "USA",
"states": [
{
"stateCode": "WAS"
},
{
"stateCode": "SOS"
}
]
}
],
"last": false,
"totalPages": 28,
"totalElements": 326,
"size": 12,
"number": 0,
"sort": null,
"numberOfElements": 12,
"first": true
}
Поэтому для достижения того, что я использовал Прогнозы, как показано ниже
CountryProjection.java
public interface CountryProjection {
public String getCountryName();
public String getCountryCode();
public List<StateProjection> getStates();
}
StateProjection.java
public interface StateProjection {
public String getStateCode();
}
CountryServiceImpl.java
@Repository
public interface CountryRepository extends JpaRepository<CountryDetails, Integer> {
@Query(value = "SELECT country.countryName AS countryName, country.countryCode AS countryCode FROM Country country GROUP BY country.countryId ORDER BY ?#{#pageable}",
countQuery = "SELECT COUNT(*) FROM Country country GROUP BY country.countryId ORDER BY ?#{#pageable}")
public Page<CountryProjection> findAll(Pageable pageRequest);
}
Но теперь служба возвращает любые данные состояния, как показано ниже
{
"content": [
{
"countryName": "USA",
"countryCode": "USA"
}
],
"last": false,
"totalPages": 28,
"totalElements": 326,
"size": 12,
"number": 0,
"sort": null,
"numberOfElements": 12,
"first": true
}
Как мы можем получить минимальные сведения о состоянии, как показано ниже
{
"content": [
{
"countryName": "USA",
"countryCode": "USA",
"states": [
{
"stateCode": "WAS"
},
{
"stateCode": "SOS"
}
]
}
],
"last": false,
"totalPages": 28,
"totalElements": 326,
"size": 12,
"number": 0,
"sort": null,
"numberOfElements": 12,
"first": true
}
Может ли кто-нибудь помочь мне в этом
Попробуйте использовать JsonIgnore с полями, которые вам не нужны в возвращаемом JSON
@JsonIgnore
private String stateDetails;
Вы можете использовать ключевое слово transient
с переменной, которая вам не нужна в json.
иначе вы используете
@Expose String myString;
ИМО есть что-то не так, как вы делаете. Я не понимаю, почему вы определяете запрос так:
@Query(value = "SELECT country.countryName AS countryName, country.countryCode AS countryCode FROM Country country GROUP BY country.countryId ORDER BY ?#{#pageable}",
countQuery = "SELECT COUNT(*) FROM Country country GROUP BY country.countryId ORDER BY ?#{#pageable}")
который в основном создает проекцию по выбору.
С другой стороны, вы используете проекции на основе интерфейса, которые еще раз выполняют проекцию, но подвергая геттеры свойствам, которые вы хотите спроектировать. Насколько я мог видеть, вы хорошо определили иерархию через интерфейсы, и это должен быть действительный подход.
Так что я спрашиваю, пытались ли вы удалить часть @Query
?
Другая идея может заключаться в использовании конструкции jpql
join fetch
в jpql
которая используется, чтобы сказать, чтобы спящий режим загружал ассоциацию с запросом.
@Query(value = "SELECT country.countryName AS countryName, country.countryCode AS countryCode, countryStates FROM Country country join fetch country.states countryStates GROUP BY country.countryId ORDER BY ?#{#pageable}"
Вы можете проверить документацию аннотации:
@JsonIgnoreProperties ( "имя_поль")
Эта аннотация должна применяться к вашим классам POJO в вашем случае Country *, State *, указывая список разделенных запятыми полей, которые вам не нужны, чтобы быть частью ответа.
Вы можете попробовать этот подход вместо перехода к реализации в стиле проецирования.
@JsonIgnoreProperties({ "id","countryDetails","countryZone"})
public class CountryDetails
@JsonIgnoreProperties({ "id","stateName","countryCode","stateDetails","stateZone"})
public class State
Вы можете заставить свой CountryService
возвращать DTO вместо сущности только с необходимыми полями.
@Service
public class CountryServiceImpl implements CountryService {
@Autowired
private CountryRepository countryRepository;
@Override
public Page<CountryDetailsDto> getAllCountryDetails(final int page, final int size) {
return countryRepository.findAll(new PageRequest(page, size))
.map(c -> {
CountryDetailsDTO dto = new CountryDetailsDTO();
dto.setCountryCode(c.getCountryCode());
dto.setCountryName(c.getCountryName());
dto.setStates(c.getStates().stream().map(s -> {
StateDto stateDto = new StateDto();
stateDto.setStateCode(s.getStateCode());
return stateDto;
}).collect(Collectors.toSet()));
return dto;
});
}
}
public class CountryDetailsDTO {
private String countryName;
private String countryCode;
private Set<StateDto> states;
}
public class StateDto {
private String stateCode;
}