web-dev-qa-db-ja.com

春の予測が州の詳細を返さない

Spring DataJPAと統合した国と州のテーブルがあります。関数を作成しました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
}

誰かがこれについて私を助けてくれますか

18
Alex Man

返されるJSONで不要なフィールドでJsonIgnoreを使用してみてください

@JsonIgnore
private String stateDetails;
1
Tarun Jain

アノテーションのドキュメントを確認できます:

@JsonIgnoreProperties( "fieldname")

このアノテーションは、ケースの国*、州*のPOJOクラスに適用する必要があり、応答の一部である必要のないフィールドのコンマ区切りリストに言及します。

投影スタイルの実装に変更する代わりに、このアプローチを試すことができます。

@JsonIgnoreProperties({ "id","countryDetails","countryZone"})
public class CountryDetails

@JsonIgnoreProperties({ "id","stateName","countryCode","stateDetails","stateZone"})
public class State
0
Rizwan

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;
                });
    }
}

DTO

public class CountryDetailsDTO {

    private String countryName;

    private String countryCode;

    private Set<StateDto> states;
}
public class StateDto {

    private String stateCode;
}
0
Robin Rozo

transientキーワードは、json内で不要な変数とともに使用できます。

それ以外の場合は使用します

@Expose String myString;
0
manish singh

最初のアイデア

IMOあなたが物事をしている方法に正しくない何かがあります。なぜこのようにクエリを直接定義しているのかわかりません。

@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}")

これは基本的に、selectによって投影を作成することです。

一方、 Interface-based Projections を使用していますが、これは再びプロジェクションを実行していますが、プロジェクションするプロパティのゲッターを公開しています。私が見る限り、あなたはインターフェースを通して階層をうまく定義しました、そしてそれは有効なアプローチであるはずです。

だから私が求めているのは、@Queryの部分をまとめて削除しようとしたことですか?

2番目のアイデア(コメントの観点から)

もう1つのアイデアは、jpqljoin fetchconstruct を使用することです。これは、クエリとの関連付けを熱心にロードするために休止状態にするために使用されます。

@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}"
0
NiVeR