[英]Java Lazy Loading with Hibernate/JPA/Spring
我在將應用程序轉換為單獨的REST Server + Web應用程序時遇到問題,而不是擁有一個處理頁面+業務邏輯的應用程序。
我在Jackson序列化輸出時拋出org.hibernate.LazyInitializationException問題。
以下是我的JPA配置和相關的類。 我知道延遲初始化是由List成員引起的,但是我不希望在返回的JSON中填充它。 因此,@ JsonIgnore批注。
PersistenceConfiguration.java
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackageClasses = {ForumRepository.class})
public class PersistenceConfiguration {
@Bean
public EntityManagerFactory entityManagerFactory() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("com.mypackage.forum.api.models");
factory.setDataSource(secureDataSource());
factory.afterPropertiesSet();
return factory.getObject();
}
@Bean
public JpaTransactionManager transactionManager() {
EntityManagerFactory factory = entityManagerFactory();
return new JpaTransactionManager(factory);
}
@Bean
public HibernateExceptionTranslator exceptionTranslator() {
return new HibernateExceptionTranslator();
}
@Bean
public DataSource secureDataSource() {
try {
Context ctx = new InitialContext();
return (DataSource) ctx.lookup("java:jboss/datasources/ForumDS");
} catch (Exception e) {
return null;
}
}
}
ForumGroup.java
@Entity
public class ForumGroup {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@JsonIgnore
@OneToMany(mappedBy = "group")
private List<Forum> forums;
private String name;
private String description;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public List<Forum> getForums() {
return forums;
}
public void setForums(List<Forum> forums) {
this.forums = forums;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ForumGroup that = (ForumGroup) o;
if (id != null ? !id.equals(that.id) : that.id != null) return false;
if (name != null ? !name.equals(that.name) : that.name != null) return false;
return true;
}
@Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + (name != null ? name.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "ForumGroup{" +
"id=" + id +
", name='" + name + '\'' +
", description='" + description + '\'' +
'}';
}
}
我以為我需要配置某種會話管理器,但是不確定在JavaConfig中執行此操作的最佳方法,我已經通過Google嘗試了各種方法,但都不太高興。
任何幫助將非常感激。
更新
我現在設法通過以下方法解決此問題:1)在相關集合中添加@Fetch()批注,這意味着將填充集合2)我已停止將實體/模型作為JSON對象返回,而是使用單獨的DTO
當從會話外部調用惰性字段時,會發生org.hibernate.LazyInitializationException
。
在您所處的情況下,您可以選擇ForumGroup
實體,然后在會話之外嘗試調用entity.getForums()
。 這就是為什么發生LazyInitializationException
的原因。
如果您需要該集合,請急切加載它們。 您可以通過以下方式實現:
entity.getForums().size();
。 記住,在會話中調用它
您可以使用注釋默認情況下自動加載EAGERLY : @ManyToOne(fetch = FetchType.EAGER)
您只需要獲取ForumGroup及其論壇列表即可。
每當您檢索感興趣的ForumGroup時,都可以使用LEFT JOIN FETCH來實現:
"from ForumGroup as fg " +
"left join fetch fg.forums "
您可以分配默認的提取策略,但這是一個會影響后續查詢的決定,因此請確保您知道以下折衷方案:
使用聯接獲取模式:
@JsonIgnore
@OneToMany(mappedBy = "group")
@Fetch(FetchMode.JOIN)
private List<Forum> forums = new ArrayList<Forum>();
或子選擇獲取模式:
@JsonIgnore
@OneToMany(mappedBy = "group")
@Fetch(FetchMode.SUBSELECT)
private List<Forum> forums = new ArrayList<Forum>();
並且始終初始化您的集合,永遠不要讓它們分配為null。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.