Jackson @JsonView JPA/Hibernate 实体图上的长关联链



我有以下代码:

public interface JSONInvoiceView {
public interface JSONInvoiceBasicView {
}
public interface JSONInvoiceWithLinesView extends JSONInvoiceBasicView {
}
}
@PersistenceUnit(unitName="ERP_PU")
@Entity 
@Table(name="INVOICE")
public class Invoice extends FrameworkEntity {
@Id
@SequenceGenerator(name = "PK_INVOICE_GEN", sequenceName = "PK_INVOICE_GEN", allocationSize=1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "PK_INVOICE_GEN")
@Column(name = "ID")
@JsonView(JSONInvoiceView.JSONInvoiceBasicView.class)
private Long id;
@OneToMany(mappedBy="invoiceLine", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JsonView(JSONInvoiceView.JSONInvoiceWithLinesView.class)
@JsonManagedReference
private List<InvoiceLine> lines = new ArrayList<InvoiceLine>();
@Temporal(TemporalType.DATE)
@Column(name = "DATE")
@JsonView(JSONInvoiceView.JSONInvoiceBasicView.class)
private Date startDate;
//...
}
@PersistenceUnit(unitName="ERP_PU")
@Entity 
@Table(name="INVOICE_LINE")
public class InvoiceLine extends FrameworkEntity {
@Id
@Column(name = "ID")
@JsonView(JSONInvoiceView.JSONInvoiceWithLinesView.class)
private Long id;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
@JoinColumn(name="FK_INVOICE")
@JsonBackReference
private Invoice invoice;
@Column(name = "AMOUNT")
@JsonView(JSONInvoiceView.JSONInvoiceWithLinesView.class)
private BigDecimal amount;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
@JoinColumn(name="FK_GOOD")
private Good good;
//...
}
@PersistenceUnit(unitName="ERP_PU")
@Entity 
@Table(name="GOOD")
public class Good extends FrameworkEntity {
@Id
@Column(name = "ID")
private Long id;
@Column(name = "DESCRIPTION", length=200)
private String description;
//...
}

因此,一张发票可以有多个发票行,并且每行都引用了"良好"。我需要获取两个 JSON 视图:仅 Inovice 视图和仅发票 + 发票行视图。我的领域比这 3 个类丰富得多——整个实体图涉及数十个类,我需要仔细控制我在实体中加载了多少这个图。但我还需要控制 JSON 序列化工具应该尝试序列化多少加载的图形。我对第二个控件有问题。

entityList是已加载 InvoiceLines 的发票列表(带触摸,例如 invoiceLines.size((;)但 InvoiceLines 没有进一步加载货物(invoiceLine.good 在延迟加载期间不被触及(。因此,实体列表如果发票+发票行。

我将以下代码用于仅发票视图,并且此代码有效:

jsonString = objectMapper.writerWithView(JSONInvoiceView.JSONInvoiceBasicView.class).writeValueAsString(entityList);

用于检索包含发票+发票行数据的 JSON 视图的代码:

jsonString = objectMapper.writerWithView(JSONInvoiceView.JSONInvoiceWithLinesView.class).writeValueAsString(entityList);

并且此代码不起作用,它会引发错误消息:

org.codehaus.jackson.map.JsonMappingException: could not initialize proxy - no Session (through reference chain: java.util.ArrayList[0]->mycom.entities.Invoice["invoiceLines"]->org.hibernate.collection.internal.PersistentBag[0]-> mycom.entities.Good["good"]-> mycom.entities.Good_$$_jvst4f9_c["id"])
at org.codehaus.jackson.map.JsonMappingException.wrapWithPath(JsonMappingException.java:218)
at org.codehaus.jackson.map.JsonMappingException.wrapWithPath(JsonMappingException.java:183)
at org.codehaus.jackson.map.ser.std.SerializerBase.wrapAndThrow(SerializerBase.java:140)
at org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:158)
at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:112)
Caused by: org.hibernate.LazyInitializationException: could not initialize proxy - no Session
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:165)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:286)

所以,问题是 -我应该将哪些杰克逊视图/注释应用于仅加载发票+发票行数据的实体图的序列化发票+发票行部分?我应该如何表明杰克逊不应该试图沿着关联链走得更远,杰克逊不应该试图序列化第 3、4 等顺序关联,杰克逊不应该尝试序列化好的实体?

p.s. 忽略注释(或实体上的任何类似全局注释(不适用于我的情况,因为在某些情况下我只需要发票数据,然后会出现我需要发票+发票行+良好数据的情况,此外,我将需要数据发票+发票行+好+好供应商等。

我找到了解决方案 - 杰克逊将没有注释@JsonView字段视为属于每个视图的字段。因此,我应该引入其他观点:

公共接口 JSONInvoiceView {

public interface JSONInvoiceBasicView {
}
public interface JSONInvoiceWithLinesView extends JSONInvoiceBasicView {
}
public interface JSONInvoiceWithLinesViewExt extends JSONInvoiceWithLinesView { 
}
}

并将新的交互应用于"好"字段:

@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
@JoinColumn(name="FK_GOOD")
@JsonView(JSONInvoiceView.JSONInvoiceWithLinesExtView.class)
private Good good;

所以 - 我应该为我的实体的每个关联级别定义新的 JSON 视图交互。应用后@JsonView一切都像魅力一样。

最新更新