本文是我用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;
- }
@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;
- }
@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;
-
-
-
-
-
-
- public void saveNews(int cid,News news) {
- news.setCategory(em.find(Category.class, cid));
- em.persist(news);
- }
-
-
-
-
-
- @SuppressWarnings("unchecked")
- public List<News> listNews() {
- return (List<News>)em.createQuery("from News n").getResultList();
- }
@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();
- }
- }
//測試保存新聞
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();
- for(News news : newsList) {
- System.out.println("news.title = " + news.getTitle());
- }
- }
//測試保存新聞
@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
- (……相關的異常堆棧信息略……)
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還是我的程序有錯誤?請大家討論!