jon*_*jon 10 java hibernate jpa lazy-loading jersey-2.0
这是一个简化的POJO我有:
@Entity
@Table( name = "Patient" )
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn
(
name="Discriminator",
discriminatorType=DiscriminatorType.STRING
)
@DiscriminatorValue(value="P")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Patient implements Serializable{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name = "ID", unique = true, nullable = false)
protected Integer ID;
@ManyToOne(targetEntity = TelephoneType.class, fetch=FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name="IDPhoneType")
protected TelephoneType phoneType;
@JsonProperty(required=false, value="phoneType")
public TelephoneType getPhoneType() {
return phoneType;
}
public void setPhoneType(TelephoneType phoneType) {
this.phoneType = phoneType;
}
}
Run Code Online (Sandbox Code Playgroud)
现在这是我的班级TelephoneType:
@Entity
@Table( name = "TelephoneType" )
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
@JsonAutoDetect(getterVisibility=Visibility.NONE, isGetterVisibility=Visibility.NONE, fieldVisibility=Visibility.NONE)
public class TelephoneType implements Serializable{
private static final long serialVersionUID = -3125320613557609205L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name = "ID", unique = true, nullable = false)
private Integer ID;
@Column(name = "Name")
private String name;
@Column(name = "Description")
private String description;
public TelephoneType() {
}
@JsonProperty(value="id")
public int getID() {
return ID;
}
public void setID(int iD) {
ID = iD;
}
@JsonProperty(value="name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@JsonProperty(value="description")
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
Run Code Online (Sandbox Code Playgroud)
}
我用的是@JsonAutoDetect注释中TelephoneType的原因是第一个自定义的JSON属性名(我需要禁用默认jsonautodetect),也因为取队列的时候,如果我不这样做,我得到一个错误
没有串行找到类org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer和没有发现通过参考链创建BeanSerializer(以避免异常,禁用SerializationFeature.FAIL_ON_EMPTY_BEANS))(属性:my.package.Patient ["PHONETYPE"] - > my.package.TelephoneType _ _ $$ jvste17_13 [ "处理程序"])
因此,如果没有@JsonAutoDetect注释,我会收到错误并且注释没有发生延迟加载,并且总是在json响应中加载TelephoneType.
我使用Criteria来进行查询:
return this.entityManager.find(Patient.class, primaryKey);
Run Code Online (Sandbox Code Playgroud)
我还补充说,正如我在不同的帖子中读到的那样,我的应用程序的web.xml中的以下内容(Jersey API):
<filter>
<filter-name>OpenEntityManagerInViewFilter</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>OpenEntityManagerInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Run Code Online (Sandbox Code Playgroud)
现在,不知何故,我肯定错过了我的配置的东西,但无法弄清楚什么,我们在许多分贝关系@ManyToOne被大大减缓API(比我的例子显示了一些较重的物体),所以我真的很欣赏找到一种激活这种懒惰装载的方法......
如果您使用的是JSON,那么我假设您通过REST端点提供结果.然后发生的是您将Patient
实体传递回REST服务.当REST服务,泽西岛在这种情况下,serializes
在Patient
其接触的所有属性,甚至实体走过它们,从而建立为完成一棵树越好.为了做到这一点,每次Jersey命中一个尚未初始化的属性时,Hibernate会再次调用数据库.这只有在EntityManager
尚未关闭的情况下才有可能.
这就是你必须OpenEntityManagerInViewFilter
安装的原因.没有它,EntityManager
当你退出服务层并且得到一个时,它就会被关闭LazyInitializationException
.在OpenEntityManagerInViewFilter
打开EntityManager
在视图级别和保持打开状态,直到HTTP请求完成.因此,虽然它看起来像是一个修复,但实际上并不是因为,正如您所看到的,当您失去对访问实体属性的人的控制权时,在这种情况下Jersey
,您最终会加载您不想加载的内容.
最好删除OpenEntityManagerInViewFilter
并找出你想要Jersey
序列化的内容.一旦你弄明白了,至少有两种方法可以解决它.IHMO,"最佳实践"是拥有DTO或数据传输对象.这些POJO不是实体,但具有几乎相同的字段.在这种情况下,PatientDTO
将拥有除phoneType
属性之外的所有内容(或者可能只是Id).你可以Patient
在构造函数中传递它,它会复制你希望Jersey序列化的字段.然后,您的服务层将负责返回DTO,而不是Entities
至少为REST端点返回DTO .您的客户端将获得代表这些DTO的JSON图表,从而可以更好地控制JSON中的内容,因为您将DTO与其分开编写Entities
.
另一种选择是使用JSON注释来防止Jersey尝试序列化您不希望序列化的属性,例如phoneType
,但最终会成为问题.会有相互矛盾的要求,你永远不会把它整理好.
虽然最初制作DTO似乎是一种可怕的痛苦,但它并不像它看起来那么糟糕,甚至在你想要序列化更客户友好的值时也会有所帮助.所以,我的建议是丢失OpenEntityManagerInViewFilter
并构造一个适当的服务层来返回DTO,或者查看对象,因为它们有时被称为.
参考文献:什么是数据传输对象?
归档时间: |
|
查看次数: |
2009 次 |
最近记录: |