私は遅延ロードモードでSparkJavaで休止状態を使用してエラーを持っています。
それはSparkJavaせずに正常に動作しているが、SparkJavaを使用した場合には、OneToMany関係のために熱心なロードを強制しようとしています。
- モデル
@Entity
@Table(name = "KU_SUPPLIER")
public class Supplier {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@NotEmpty(message = "Please provide a name")
private String name;
@OneToMany(mappedBy = "supplier")
private List<Item> items; // Should be lazy-loaded
// Constructor / Getters / Setters
}
- DAO
public class SupplierDao implements Dao<Supplier> {
private final SessionFactory sessionFactory;
public SupplierDao(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
@Override
@SuppressWarnings("unchecked")
public List<Supplier> findAll() {
try (Session session = sessionFactory.openSession()) {
return session.createQuery("FROM com.seafrigousa.model.Supplier").getResultList();
}
}
}
- メイン
// Working perfectly and lazy-load Items as desired
supplierDao.findAll();
// The method will be called when a web browser goes to "localhost/suppliers"
// It throws org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: model.Supplier.items, could not initialize proxy - no Session
get("/suppliers", "application/json", supplierDao::findAll);
私はDAOからセッションを閉じていないことで確認し、私はそれがEAGERロードモードにあったかのように、2つの選択、サプライヤー用とアイテムのための1つを実行していたので、Hibernateは、クエリを実行していたことがわかりました。
この現象の理由はありますか?
ありがとうございました!
私はここでそれを推測:get("/suppliers", "application/json", supplierDao::findAll);
あなたは、JSONにサプライヤーのオブジェクトをシリアル化しています。Items
フィールドには、そのセッションのうち、遅延初期化の原因、その値を取得し、直列化から除外としてマークされた(またはセッションがクローズされていない場合は、アイテムのために2番目のクエリをredundand)されていません。
私の推測が正しければ、あなたのシリアライザは、アイテムのフィールドを無視するか、またはあなたのクエリでそれらを取得します
session.createQuery("FROM com.seafrigousa.model.Supplier s join fetch s.items").getResultList();
あなたはオプションを以下しているシリアライザとしてgsonを使用します:
@Expose
あなたはフィールド上の注釈たいシリアライズします。@Entity @Table(name = "KU_SUPPLIER") public class Supplier { @Expose @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; @Expose @NotEmpty(message = "Please provide a name") private String name; @OneToMany(mappedBy = "supplier") private List<Item> items; // Should be lazy-loaded // Constructor / Getters / Setters }
次gson開始と
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
カスタム注釈FeをExclusionStrategy
public class IgnoreFieldExclusionStrategy implements ExclusionStrategy { @Override public boolean shouldSkipField(FieldAttributes fieldAttributes) { return fieldAttributes.getAnnotation(GsonIgnore.class) != null; } @Override public boolean shouldSkipClass(Class<?> aClass) { return false; } }
カスタム注釈付き
@GsonIgnore
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface GsonIgnore {}
そして、gson開始
Gson gson = new GsonBuilder().addSerializationExclusionStrategy(new IgnoreFieldExclusionStrategy()).create();
あなたのクラスは次のようになります。
@Entity @Table(name = "KU_SUPPLIER") public class Supplier { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; @NotEmpty(message = "Please provide a name") private String name; @GsonIgnore @OneToMany(mappedBy = "supplier") private List<Item> items; // Should be lazy-loaded // Constructor / Getters / Setters }
あなたが必要シリアライズを持っている希望の場合Supplier
でitems
異なるAPIで、あなたがのためにDTOオブジェクトを作成することができますSupplier
し、このような結果から、それをマッピングします。
package com.seafrigousa.dto
public class SupplierDTO {
private int id;
private String name;
public SupplierDTO(int id, String name) {
this.id = id;
this.name = name;
}
// Getters / Setters
}
そして、クエリ:
session.createQuery("select new com.seafrigousa.dto.SupplierDTO(s.id, s.name) FROM com.seafrigousa.model.Supplier s").getResultList();