JSONを書き込めませんでした:LOBストリームにアクセスできません

Piter _OS

PostgreSQLを使用してSpring-Bootでサーバーを作成しています。特定のエンティティにリンクされているイメージに関する情報を取得しようとしています。サーバーからフロントエンドのAngularアプリにユーザー情報を取得しようとしています。私のシステムでは、ユーザーは自分のアカウントにリンクされた画像を持っているので、クラスImageEntityを実行しました

@Entity @Table(name = "image") @Data
public class ImageEntity {
   @Id @GeneratedValue(strategy = GenerationType.SEQUENCE)
   private Long id;
   private String name;
   private String type;
   @Lob
   private byte[] image;

   @JsonIgnore
   public byte[] getImage() {
       return image;
   }
}

次に、画像のリストをユーザーアカウントクラスにリンクしました

@Entity @Data
public class UserAccount{
@Id @GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
private String firstName;
private String lastName

@OneToMany(cascade = CascadeType.ALL)
@JoinTable(
        name = "user_images",
        joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")},
        inverseJoinColumns = {@JoinColumn(name = "image_id", referencedColumnName = "id")}
)
private List<ImageEntity> images;

public void addImage(ImageEntity image) {
    images.add(image);
}
}

次に、IDでユーザーを取得するエンドポイントを作成します

@GetMapping("users/{id}")
public Optional<User> getUserById(@PathVariable Long id) {
    return service.getUserById(id);
}

サービス方法はとても簡単です

@Transactional
public Optional<User> getUserById(Long id) {
    return repository.findById(id);
}

フロントエンドで画像を取得できるため、別のエンドポイントを介していくつかの画像を追加しても問題なく動作します。

問題は、サーバーからユーザー情報をJSONとして取得したい場合です(実際の画像ではなく画像の情報のみを取得したいので、@ Lobフィールドに@JsonIgnoreと書き込みます)このエラーが発生します

Resolved exception caused by handler execution: org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Unable to access lob stream; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Unable to access lob stream (through reference chain: com.app.model.user.User["images"])

私はいくつかの同様の記事を読み、画像のゲッターで@JsonIgnoreを与えようとしました@Lob画像私は要素を取得するサービスメソッドに@Transactionalを追加しましたが、それは機能していません。

私は単にサーバーからその種のメッセージを達成したいのです:

{
 id: "1"
 firstName: "test",
 lstName: "test_ln",
 images: {
    {
        "id": 10,
        "name": "IMG12.jpg",
        "type": "image/jpeg"
    },
    {
        "id": 20,
        "name": "IMG456.jpg",
        "type": "image/jpeg"
    }
 }
}
カーリトスウェイ

最速の解決策(最良の解決策ではありません)はfecth = EAGEROneToMany画像の関係に追加することです...この解決策の問題は、ユーザーエンティティ(可能性があります)を処理するときに常に画像エンティティ(byte []画像を含む)をロードすることですパフォーマンスの問題)..。

次の「最善の」解決策は、EAGER前述構成を省略し、リポジトリに新しいメソッドを作成することです...このようなメソッドは次のようなJPAクエリを実行する必要があります。

SELECT ua
FROM
    UserAccount ua
    LEFT JOIN FECTH ua.images img
WHERE
    ua.id = :id

これにより、ユーザーとその関連画像が読み込まれます...次に、サービスでそのようなメソッドを呼び出します(このソリューションの問題はimage、の他の属性のみが必要な場合でも、byte []を読み込むことですImageEntity

最善の解決策は、ソリューション#2を拡張して、必要な属性のみを取得することですImageEntity。その結果、次のようなクエリが生成されます。

SELECT
    ua,
    img.id, img.name, img.type
FROM
    UserAccount ua
    LEFT JOIN ua.images img
WHERE
    ua.id = :id

次に、リポジトリメソッドはJPATuple返す必要があり、サービスメソッドでは、そのタプルを返したいユーザーに変換します(関連する画像のメタデータを含む)... (UPDATE)例(コメントで指定したメソッドを使用)::

// @Transactional  // Remove the transactional annotation to avoid cascade issues!
public User getUserById(Long id) {
    List<ImageEntity> images;
    List<Tuple> tuples;
    User user;

    tuples = repository.getUserById(id);
    user   = null;

    if (!tuples.isEmpty()) {
        user   = tuples.get(0).get(0, User.class);
        images = new ArrayList<>();

        for (Tuple t : tuples) {
            if (t.get(1) != null) {
                images.add(new ImageEntity(
                    t.get(1, Long.class),
                    t.get(2, String.class)
                ));
            }
        }
        user.setImages(images);
    }
    return user;
}

これを機能させるには、次のものが必要です。

  1. getUserById(リポジトリ内の)メソッドのシグネチャを変更してタプルのリストを返します
  2. 次のシグニチャを使用して、ImageEntityクラスにコンストラクタメソッドを作成します。 ImageEntity(long id, String name) { ... }
  3. ユーザーエンティティにはメソッドが必要です setImages(List<ImageEntity> images) { ... }

UPDATE2:このようなことを行うには、すべてのユーザーを取得するときに、次のものが必要になります。

1)クエリが次のようになるメソッドをユーザーリポジトリに作成(またはオーバーライド)します(それをfindAllと呼びましょう):

SELECT
    ua,
    img.id, img.name, img.type
FROM
    UserAccount ua
    LEFT JOIN ua.images img

2)サービスで、次のようなメソッドを実装します。

public List<User> findAll(Long id) {
    List<ImageEntity> images;
    List<Tuple> tuples;
    Map<Long, User> index;

    tuples = repository.findAll();
    index  = new HashMap<>();

    for (Tuple t : tuples) {
        user = t.get(0, User.class);

        if (!index.containsKey(user.getId()) {
            images = new ArrayList<>();

            user.setImages(images);
            index.put(user.getId(), user)
        } else {
            user   = index.get(user.getId());
            images = user.getImages():
        } 

        if (t.get(1) != null) {
            images.add(new ImageEntity(
               t.get(1, Long.class),
               t.get(2, String.class)
            ));
        }
    }
    return index.values();
}

説明:重要な点は、画像メタデータ(コード、名前、タイプのみ)を使用してユーザーを取得し、lob属性を読み込まないようにすることです(画像はMBである可能性があり、使用/シリアル化されないため)。 。そのため、次のようなクエリを実行します。

    SELECT
    ua,
    img.id, img.name, img.type
FROM
    UserAccount ua
    LEFT JOIN ua.images img
  • LEFT JOIN(画像のないものを含む)すべてのユーザーを取得するための力

  • ORM(つまり、JPA実装、たとえばHibernate)は、この種のクエリをタプルオ​​ブジェクトに(常に)マップします!

  • クエリはNx Mタプルを生成します...ここで、Nはユーザーの合計であり、Mは画像の合計です...たとえば、2つの画像を持つユーザーが1人しかない場合、結果は2つのタプルになります。タプルのコンポーネントは常に同じユーザーであり、他のコンポーネントは各画像の属性になります。

  • 次に、タプルオブジェクトをユーザーオブジェクトに変換する必要があります(これはサービスメソッドで行うことです)...ここでの重要なポイントは、ArrayList新しいImageEntityを追加する前に、images属性にnewを使用することです。 。ORMはロードされたユーザーごとにプロキシリストを挿入するため、これを行う必要があります...このプロキシに何かを追加すると、ORMはそのようなプロキシの遅延読み込みを実行し、関連する画像を取得します(これは私たちがしたいことです)避ける)...

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

findByDescriptionContaining(String description)のlobストリームにアクセスできません

分類Dev

WindowsでSBTプロセスにストリームを書き込めません

分類Dev

UpdateListItemsは、「閉じたストリームにアクセスできません」をスローします。

分類Dev

bumblebee ::セカンダリGPUにアクセスできません-エラー:GPUドライバーを読み込めませんでした

分類Dev

SparkスクリプトでSparkデータセットをHBaseに書き込めません

分類Dev

RestClientException:リクエストを書き込めませんでした:リクエストタイプに適したHttpMessageConverterが見つかりません

分類Dev

ストリーミングに大量のデータを書き込めませんでした

分類Dev

Nexusはリソースを書き込めませんでした

分類Dev

WCF:閉じたストリームにアクセスできません

分類Dev

ClosedXml閉じたストリームにアクセスできません

分類Dev

C#-閉じたストリームにアクセスできません

分類Dev

EPPlusは閉じたストリームにアクセスできません

分類Dev

いいえ-エラー:GPUドライバーを読み込めませんでした。セカンダリGPUにアクセスできません-エラー:GPUドライバーを読み込めませんでした

分類Dev

いいえ-エラー:GPUドライバーを読み込めませんでした。セカンダリGPUにアクセスできません-エラー:GPUドライバーを読み込めませんでした

分類Dev

カスタム辞書データをplistファイルに書き込めませんでした

分類Dev

データを書き込むために Beanshell スクリプトを使用して DB に HTTPS 呼び出しを行うことができません

分類Dev

ネットワークにリンクを追加するためにネストされた辞書の値にアクセスできません

分類Dev

ILMergeを介してDLLをexeに埋め込みました。dllにアクセスできません。

分類Dev

VBA:セル値をテキストファイルに書き込めませんでした

分類Dev

JSON アイテムにアクセスできませんでした

分類Dev

アクセストークンを正常に生成した後、PHPにPowerBIレポートの埋め込みトークンを取得できません

分類Dev

Spark API を使用して MySQL に書き込めません - pickle.PicklingError: オブジェクトをシリアル化できませんでした

分類Dev

クラスルーター/ルートを書き込めませんでした

分類Dev

IEは、埋め込まれたswfsをインターネットにロードできませんが、ローカルでアクセスできます。

分類Dev

ファイルへのリクエストで取得したHTMLを書き込めません

分類Dev

マルチプロセッシング-リストをcsvに書き込めません(TypeError: 'ApplyResult'オブジェクトは反復できません)

分類Dev

寄木細工の流しにストリームを書き込むことができません

分類Dev

Gmail API:リクエストしたメッセージのリストにアクセスできません

分類Dev

WebAPIにリモートでアクセスできません

Related 関連記事

  1. 1

    findByDescriptionContaining(String description)のlobストリームにアクセスできません

  2. 2

    WindowsでSBTプロセスにストリームを書き込めません

  3. 3

    UpdateListItemsは、「閉じたストリームにアクセスできません」をスローします。

  4. 4

    bumblebee ::セカンダリGPUにアクセスできません-エラー:GPUドライバーを読み込めませんでした

  5. 5

    SparkスクリプトでSparkデータセットをHBaseに書き込めません

  6. 6

    RestClientException:リクエストを書き込めませんでした:リクエストタイプに適したHttpMessageConverterが見つかりません

  7. 7

    ストリーミングに大量のデータを書き込めませんでした

  8. 8

    Nexusはリソースを書き込めませんでした

  9. 9

    WCF:閉じたストリームにアクセスできません

  10. 10

    ClosedXml閉じたストリームにアクセスできません

  11. 11

    C#-閉じたストリームにアクセスできません

  12. 12

    EPPlusは閉じたストリームにアクセスできません

  13. 13

    いいえ-エラー:GPUドライバーを読み込めませんでした。セカンダリGPUにアクセスできません-エラー:GPUドライバーを読み込めませんでした

  14. 14

    いいえ-エラー:GPUドライバーを読み込めませんでした。セカンダリGPUにアクセスできません-エラー:GPUドライバーを読み込めませんでした

  15. 15

    カスタム辞書データをplistファイルに書き込めませんでした

  16. 16

    データを書き込むために Beanshell スクリプトを使用して DB に HTTPS 呼び出しを行うことができません

  17. 17

    ネットワークにリンクを追加するためにネストされた辞書の値にアクセスできません

  18. 18

    ILMergeを介してDLLをexeに埋め込みました。dllにアクセスできません。

  19. 19

    VBA:セル値をテキストファイルに書き込めませんでした

  20. 20

    JSON アイテムにアクセスできませんでした

  21. 21

    アクセストークンを正常に生成した後、PHPにPowerBIレポートの埋め込みトークンを取得できません

  22. 22

    Spark API を使用して MySQL に書き込めません - pickle.PicklingError: オブジェクトをシリアル化できませんでした

  23. 23

    クラスルーター/ルートを書き込めませんでした

  24. 24

    IEは、埋め込まれたswfsをインターネットにロードできませんが、ローカルでアクセスできます。

  25. 25

    ファイルへのリクエストで取得したHTMLを書き込めません

  26. 26

    マルチプロセッシング-リストをcsvに書き込めません(TypeError: 'ApplyResult'オブジェクトは反復できません)

  27. 27

    寄木細工の流しにストリームを書き込むことができません

  28. 28

    Gmail API:リクエストしたメッセージのリストにアクセスできません

  29. 29

    WebAPIにリモートでアクセスできません

ホットタグ

アーカイブ