亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何在控制器中從Hibernate / JPA加載延遲獲取的項目

如何在控制器中從Hibernate / JPA加載延遲獲取的項目

UYOU 2019-11-22 15:25:50
我有一個Person類:@Entitypublic class Person {    @Id    @GeneratedValue    private Long id;    @ManyToMany(fetch = FetchType.LAZY)    private List<Role> roles;    // etc}與多對多的關系是懶惰的。在我的控制器中@Controller@RequestMapping("/person")public class PersonController {    @Autowired    PersonRepository personRepository;    @RequestMapping("/get")    public @ResponseBody Person getPerson() {        Person person = personRepository.findOne(1L);        return person;    }}而PersonRepository只是此代碼,是根據本指南編寫的public interface PersonRepository extends JpaRepository<Person, Long> {}但是,在此控制器中,我實際上需要惰性數據。如何觸發加載?嘗試訪問它將會失敗無法延遲初始化角色集合:no.dusken.momus.model.Person.roles,無法初始化代理-沒有會話或其他例外情況,具體取決于我的嘗試。我的xml-description,如果需要的話。謝謝。
查看完整描述

3 回答

?
叮當貓咪

TA貢獻1776條經驗 獲得超12個贊

您必須對延遲集合進行顯式調用才能對其進行初始化(通常的做法是.size()為此目的而調用)。在Hibernate中,有一個專用于此(Hibernate.initialize())的方法,但是JPA沒有與此等效的方法。當然,當會話仍然可用時,您必須確保調用已完成,因此請使用注釋控制器方法@Transactional。一種替代方法是在控制器和存儲庫之間創建一個中間服務層,該服務層可以公開初始化惰性集合的方法。


更新:

請注意,上述解決方案很簡單,但是會導致對數據庫進行兩個不同的查詢(一個用于用戶,另一個用于其角色)。如果要獲得更好的性能,請在Spring Data JPA存儲庫接口中添加以下方法:


public interface PersonRepository extends JpaRepository<Person, Long> {


    @Query("SELECT p FROM Person p JOIN FETCH p.roles WHERE p.id = (:id)")

    public Person findByIdAndFetchRolesEagerly(@Param("id") Long id);


}

此方法將使用JPQL的fetch join子句在一次往返數據庫中熱切地加載角色關聯,因此將減輕上述解決方案中兩個截然不同的查詢引起的性能損失。


查看完整回答
反對 回復 2019-11-22
?
30秒到達戰場

TA貢獻1828條經驗 獲得超6個贊

盡管這是一篇老文章,但請考慮使用@NamedEntityGraph(Javax Persistence)和@EntityGraph(Spring Data JPA)。組合有效。



@Entity

@Table(name = "Employee", schema = "dbo", catalog = "ARCHO")

@NamedEntityGraph(name = "employeeAuthorities",

            attributeNodes = @NamedAttributeNode("employeeGroups"))

public class EmployeeEntity implements Serializable, UserDetails {

// your props

}

然后如下所示的春季回購


@RepositoryRestResource(collectionResourceRel = "Employee", path = "Employee")

public interface IEmployeeRepository extends PagingAndSortingRepository<EmployeeEntity, String>           {


    @EntityGraph(value = "employeeAuthorities", type = EntityGraphType.LOAD)

    EmployeeEntity getByUsername(String userName);


}


查看完整回答
反對 回復 2019-11-22
?
波斯汪

TA貢獻1811條經驗 獲得超4個贊

你有一些選擇


根據RJ建議,在存儲庫上編寫一個返回初始化實體的方法。

更多工作,最佳性能。


使用OpenEntityManagerInViewFilter可使整個請求的會話保持打開狀態。

工作量少,通常在網絡環境中可以接受。


需要時,使用幫助器類來初始化實體。

較少的工作,在未選擇OEMIV時(例如在Swing應用程序中)很有用,但在存儲庫實現中一次也可以初始化任何實體可能也有用。


對于最后一個選項,我編寫了一個實用程序類JpaUtils來在某些時候初始化實體。


例如:


@Transactional

public class RepositoryHelper {


    @PersistenceContext

    private EntityManager em;


    public void intialize(Object entity, int depth) {

        JpaUtils.initialize(em, entity, depth);

    }

}


查看完整回答
反對 回復 2019-11-22
  • 3 回答
  • 0 關注
  • 719 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號