本文是我用EJB+JPA(Hibernate實現)+Web Service開發時,遇到的一些問題,查了許多地方,都找不到答案,請各位朋友耐心讀一下本文,有想法的歡迎留言!謝謝!
Category.java的部分代碼:
- @OneToMany(cascade={CascadeType.ALL},fetch=FetchType.LAZY,mappedBy="category")
- public List<News> getNewsList() {
- return newsList;
- }
- public void setNewsList(List<News> newsList) {
- this.newsList = newsList;
- }
News.java的部分代碼:
- @ManyToOne(cascade={CascadeType.PERSIST,CascadeType.MERGE},fetch=FetchType.EAGER)
- @JoinColumn(name="cid")
- public Category getCategory() {
- return category;
- }
- public void setCategory(Category category) {
- this.category = category;
- }
NewsDaoBean.java的部分代碼:
- @PersistenceContext(unitName="newspstn")
- private EntityManager em;
- /**
- * 添加新聞
- * @param cid 項目編號
- * @param news
- */
- public void saveNews(int cid,News news) {
- news.setCategory(em.find(Category.class, cid));
- em.persist(news);
- }
- /**
- * 查詢所有新聞列表
- * @return
- */
- @SuppressWarnings("unchecked")
- public List<News> listNews() {
- return (List<News>)em.createQuery("from News n").getResultList();
- }
業務邏輯層的類(NewsManager.java)比較簡單,由于篇幅問題,這里就不貼出來了。
在還沒有發布成Web Service前,用Juint測試:
- //測試保存新聞
- public void testSaveNews() {
- InitialContext ctx;
- try {
- ctx = new InitialContext();
- NewsManager manager = (NewsManager)ctx.lookup("NewsManagerBean/remote");
- News news = new News();
- news.setTitle("title2");
- news.setAuthor("author2");
- news.setContent("content1");
- manager.saveNews(1, news);
- } catch (NamingException e) {
- System.out.println("NamingException");
- e.printStackTrace();
- }
- }
- //測試查詢新聞列表
- public void testListNews() {
- InitialContext ctx;
- try {
- ctx = new InitialContext();
- NewsManager manager = (NewsManager)ctx.lookup("NewsManagerBean/remote");
- List<News> newsList = manager.listNews();
- for(News news : newsList){
- System.out.println("news.title = " + news.getTitle());
- }
- } catch (NamingException e) {
- System.out.println("NamingException");
- e.printStackTrace();
- }
- }
這個測試是沒有問題的,(testSaveNews和testListNews)能正常添加和查詢。
當發布成Web Service后,在客戶端生成相應的服務代理類,再在Web服務的客戶端用Junit測試:
- //測試保存新聞
- @Test
- public void testSaveNews(){
- NewsManagerService service = new NewsManagerService();
- NewsManager manager = service.getNewsManagerPort();
- News news = new News();
- news.setTitle("title1");
- news.setAuthor("author1");
- news.setContent("content1");
- manager.saveNews(1, news);
- }
- //測試查詢新聞列表
- @Test
- public void testListNews(){
- NewsManagerService service = new NewsManagerService();
- NewsManager manager = service.getNewsManagerPort();
- List<News> newsList = manager.listNews(); //------a1
- for(News news : newsList) { //--------a2
- System.out.println("news.title = " + news.getTitle()); //----a3
- } //------a4
- }
這次測試,保存新聞的的操作(testSaveNews)能正常,但查詢新聞列表(testListNews)的操作卻拋以下異常:
- 12:19:37,781 INFO [STDOUT] Hibernate:
- select
- news0_.id as id1_,
- news0_.content as content1_,
- news0_.cid as cid1_,
- news0_.title as title1_,
- news0_.author as author1_,
- news0_.pubtime as pubtime1_
- from
- rong_news news0_
- 12:19:37,781 INFO [STDOUT] Hibernate:
- select
- category0_.id as id0_0_,
- category0_.cname as cname0_0_
- from
- rong_category category0_
- where
- category0_.id=?
- 12:19:37,796 ERROR [LazyInitializationException] failed to lazily initialize a collection of role: rong.entity.Category.newsList, no session or session was closed
- org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: rong.entity.Category.newsList, no session or session was closed
- (……相關的異常堆棧信息略……)
- 12:19:37,796 ERROR [RequestHandlerImpl] Error processing web service request
- org.jboss.ws.WSException: javax.xml.ws.WebServiceException: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: rong.entity.Category.newsList, no session or session was closed
- (……相關的異常堆棧信息略……)
- Caused by: javax.xml.ws.WebServiceException: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: rong.entity.Category.newsList, no session or session was closed
- (……相關的異常堆棧信息略……)
- Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: rong.entity.Category.newsList, no session or session was closed
- (……相關的異常堆棧信息略……)
- 12:19:37,890 ERROR [[NewsManagerBean]] Servlet.service() for servlet NewsManagerBean threw exception
- org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: rong.entity.Category.newsList, no session or session was closed
- (……相關的異常堆棧信息略……)
補充說明1:如果我把上面testListNews方法中的a1,a2,a3,a4行注釋掉,Junit測試是正常的。
補充說明2:在Category類中,對List<News> newsList的設置,我確定是設置了延遲加載(Lazy)的,而且,我在查詢 新聞列表時,沒有用到news.getCategory.getNewsList()之類的操作。有個疑問:是不是設置的lazy加載,即使沒有用到,也會加載的?即使會加載的,為什么我在服務器端測試時能正常,而在Web Service的客戶端測試時,卻報錯?
是EJB Web Service的Bug還是我的程序有錯誤?請大家討論!
本文原創,轉載請注明出處,謝謝!http://www.aygfsteel.com/rongxh7(心夢帆影JavaEE技術博客)