本文是我用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还是我的程序有错误?请大家讨论!