【发布时间】:2017-07-12 07:44:37
【问题描述】:
我有以下代码:
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;
//...
}
所以 – 一张 Invoice 可以有多个 InvoiceLines,并且每一行都引用 Good。我需要获得两个 JSON 视图:仅限 Inovice 视图和仅限 Invoice+InvoiceLine 视图。我的领域远比这 3 个类丰富——整个实体图包含数十个类,我需要仔细控制我在实体中加载的这个图的多少。但我还需要控制 JSON 序列化工具应该尝试序列化多少加载的图形。我对第二个控件有疑问。
entityList 是已加载 InvoiceLines 的 Invoices 列表(带有触摸,例如 invoiceLines.size();),但 InvoiceLines 没有进一步加载货物(在延迟加载期间未触摸 invoiceLine.good)。所以,entityList if Invoice+InvoiceLines。
我将以下代码用于仅发票视图,并且此代码有效:
jsonString = objectMapper.writerWithView(JSONInvoiceView.JSONInvoiceBasicView.class).writeValueAsString(entityList);
使用仅 Invoice+InvoiceLine 数据检索 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)
所以,问题是——我应该对仅加载 Invoice+InvoiceLine 数据的实体图的序列化 Invoice+InvoiceLine 部分应用什么 Jackson 视图/注释?我应该如何表明 Jackson 不应该尝试沿着关联链走得更远,Jackson 不应该尝试序列化 3rd、4th 等顺序关联,Jackson 不应该尝试序列化好的实体?
附言忽略注释(或实体上的任何类似全局注释)不适用于我的情况,因为在某些情况下我只需要 Invoice 数据,然后在某些情况下我需要 Invoice+InvoiceLine+Good 数据,而且我还需要数据Invoice+InvoiceLine+Good+GoodSupplier等
【问题讨论】:
标签: java json hibernate jpa jackson