【发布时间】:2015-01-15 00:31:04
【问题描述】:
我是trying to use a Facade class,它扩展了一个抽象外观,用 JPA 持久化一个实体。涉及的数据库类有:
src/net/bounceme/dur/selenium/jpa/
├── AbstractFacade.java
├── Feed.java
├── FeedJpaController.java
├── LinkFacade.java
├── Link.java
├── LinkJpaController.java
├── PageFacade.java
├── Page.java
└── PageJpaController.java
虽然AbstractFacade 报告成功持久化Page:
run:
[java] [EL Info]: 2014-11-17 14:56:29.301--ServerSession(23999191)--EclipseLink, version: Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd
[java] [EL Info]: connection: 2014-11-17 14:56:30.276--ServerSession(23999191)--file:/home/thufir/NetBeansProjects/SeleniumIterator/build/classes/_SeleniumIteratorPU login successful
[java] Nov 17, 2014 2:56:55 PM net.bounceme.dur.selenium.jpa.AbstractFacade create
[java] INFO: ..persisted!
[java] Nov 17, 2014 2:57:19 PM net.bounceme.dur.selenium.jpa.AbstractFacade create
[java] INFO: ..persisted!
^Cthufir@dur:~/NetBeansProjects/SeleniumIterator$
成功并没有反映在数据库中:
mysql>
mysql> select * from pages;
Empty set (0.00 sec)
mysql>
mysql> describe pages;
+---------+-----------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+---------+-----------+------+-----+-------------------+-----------------------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| created | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| page | text | NO | | NULL | |
| link_id | int(11) | NO | | 0 | |
| status | int(11) | NO | | 0 | |
+---------+-----------+------+-----+-------------------+-----------------------------+
5 rows in set (0.05 sec)
mysql>
SeleniumWebPageIterator 类正确地迭代链接:
package selenium;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import net.bounceme.dur.selenium.jpa.Link;
import net.bounceme.dur.selenium.jpa.LinkFacade;
import net.bounceme.dur.selenium.jpa.Page;
import net.bounceme.dur.selenium.jpa.PageFacade;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
public class SeleniumWebPageIterator {
private final static Logger log = Logger.getLogger(SeleniumWebPageIterator.class.getName());
private final PageFacade pageFacade = new PageFacade();
private final LinkFacade linkFacade = new LinkFacade();
public SeleniumWebPageIterator() {
}
public void processLinks() {
List<Link> links = linkFacade.findAll();
for (Link l : links) {
processLink(l);
}
}
private void processLink(Link l) {
log.fine(l.toString());
WebDriver driver = new FirefoxDriver(); //don't display
driver.get(l.getLink());
driver.manage().timeouts().implicitlyWait(9, TimeUnit.SECONDS);
String s = driver.getPageSource();
createPage(l, s);
driver.close();
}
private void createPage(Link l, String s) {
Page p = new Page();
p.setCreated(new Date());
p.setLinkId(l.getId());
p.setPage(s);
pageFacade.create(p); //page has no id..
}
}
数据库中有链接(URL),Selenium 访问了这些网页。但是,页面的源 HTML 不会被保留。
PageFacade 很简单:
package net.bounceme.dur.selenium.jpa;
import java.util.logging.Logger;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
public class PageFacade extends AbstractFacade {
private final static Logger log = Logger.getLogger(PageFacade.class.getName());
private final EntityManagerFactory emf = Persistence.createEntityManagerFactory("SeleniumIteratorPU");
// @PersistenceContext(unitName = "SeleniumReaderPU")
public PageFacade() {
super(Page.class);
}
@Override
protected EntityManager getEntityManager() {
return emf.createEntityManager();
}
}
当然还有扩展AbstractFacade:
package net.bounceme.dur.selenium.jpa;
import java.util.List;
import java.util.logging.Logger;
import javax.persistence.EntityManager;
public abstract class AbstractFacade<T> {
private final static Logger log = Logger.getLogger(AbstractFacade.class.getName());
private Class<T> entityClass;
public AbstractFacade(Class<T> entityClass) {
this.entityClass = entityClass;
}
protected abstract EntityManager getEntityManager();
public void create(T entity) {
getEntityManager().persist(entity);
log.info("..persisted!");
}
public void edit(T entity) {
getEntityManager().merge(entity);
}
public void remove(T entity) {
getEntityManager().remove(getEntityManager().merge(entity));
}
public T find(Object id) {
return getEntityManager().find(entityClass, id);
}
public List<T> findAll() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
return getEntityManager().createQuery(cq).getResultList();
}
public List<T> findRange(int[] range) {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
javax.persistence.Query q = getEntityManager().createQuery(cq);
q.setMaxResults(range[1] - range[0] + 1);
q.setFirstResult(range[0]);
return q.getResultList();
}
public int count() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
javax.persistence.criteria.Root<T> rt = cq.from(entityClass);
cq.select(getEntityManager().getCriteriaBuilder().count(rt));
javax.persistence.Query q = getEntityManager().createQuery(cq);
return ((Long) q.getSingleResult()).intValue();
}
}
使用PageJpaController 实际持久化到数据库:
package net.bounceme.dur.selenium.jpa;
import java.io.Serializable;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import net.bounceme.dur.selenium.jpa.exceptions.NonexistentEntityException;
public class PageJpaController implements Serializable {
public PageJpaController(EntityManagerFactory emf) {
this.emf = emf;
}
private EntityManagerFactory emf = null;
public EntityManager getEntityManager() {
return emf.createEntityManager();
}
public void create(Page page) {
EntityManager em = null;
try {
em = getEntityManager();
em.getTransaction().begin();
em.persist(page);
em.getTransaction().commit();
} finally {
if (em != null) {
em.close();
}
}
}
public void edit(Page page) throws NonexistentEntityException, Exception {
EntityManager em = null;
try {
em = getEntityManager();
em.getTransaction().begin();
page = em.merge(page);
em.getTransaction().commit();
} catch (Exception ex) {
String msg = ex.getLocalizedMessage();
if (msg == null || msg.length() == 0) {
Integer id = page.getId();
if (findPage(id) == null) {
throw new NonexistentEntityException("The page with id " + id + " no longer exists.");
}
}
throw ex;
} finally {
if (em != null) {
em.close();
}
}
}
public void destroy(Integer id) throws NonexistentEntityException {
EntityManager em = null;
try {
em = getEntityManager();
em.getTransaction().begin();
Page page;
try {
page = em.getReference(Page.class, id);
page.getId();
} catch (EntityNotFoundException enfe) {
throw new NonexistentEntityException("The page with id " + id + " no longer exists.", enfe);
}
em.remove(page);
em.getTransaction().commit();
} finally {
if (em != null) {
em.close();
}
}
}
public List<Page> findPageEntities() {
return findPageEntities(true, -1, -1);
}
public List<Page> findPageEntities(int maxResults, int firstResult) {
return findPageEntities(false, maxResults, firstResult);
}
private List<Page> findPageEntities(boolean all, int maxResults, int firstResult) {
EntityManager em = getEntityManager();
try {
CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
cq.select(cq.from(Page.class));
Query q = em.createQuery(cq);
if (!all) {
q.setMaxResults(maxResults);
q.setFirstResult(firstResult);
}
return q.getResultList();
} finally {
em.close();
}
}
public Page findPage(Integer id) {
EntityManager em = getEntityManager();
try {
return em.find(Page.class, id);
} finally {
em.close();
}
}
public int getPageCount() {
EntityManager em = getEntityManager();
try {
CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
Root<Page> rt = cq.from(Page.class);
cq.select(em.getCriteriaBuilder().count(rt));
Query q = em.createQuery(cq);
return ((Long) q.getSingleResult()).intValue();
} finally {
em.close();
}
}
}
<class>JpaController 的代码在另一个项目中运行良好。事实上,这些数据库操作应该是作为库在自己的项目中进行的,但我不认为底层的Page有问题,它是用“Entity Classes from Database...”创建的,同样创建的JpaController也没有问题。我根据a similar scenario添加了外观。
如何解决持久性出错的问题?
我检查了PageJpaController 接收到Page,并且该对象具有字段。然而,出于某种原因,Page 的数据库表仍然不受影响。我不确定如何进一步排除故障。
【问题讨论】:
标签: jpa orm persistence facade