2014-11-17 6 views
0

JPA로 엔티티를 유지하기 위해 추상 외관을 확장하는 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 :

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 클래스 반복 : 성공은 데이터베이스에 반영되지 않도록

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! 
^[email protected]:~/NetBeansProjects/SeleniumIterator$ 

링크 올바르게 :

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은 유지되지 않습니다. , AbstractFacade

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(); 
    } 
} 

물론, 확장 :

PageFacade은 간단하다

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(); 
     } 
    } 

} 

코드 : 실제로 데이터베이스에 지속 PageJpaController를 사용

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(); 
    } 

} 

에 대한다른 프로젝트에서 잘 작동합니다. 실제로 이러한 데이터베이스 작업은 라이브러리로 자체 프로젝트에 있어야하지만 "Entity Classes from Database..."또는 유사하게 생성 된 JpaController로 만든 Page의 문제가 있다고 생각하지 않습니다. a similar scenario에 따라 외관을 추가했습니다.

지속성에 문제가있는 경우 어떻게 해결해야합니까?

PageJpaControllerPage이고 개체에 입력란이 있는지 확인했습니다. 그러나 어떤 이유로 인해 Page의 데이터베이스 테이블은 영향을받지 않습니다. 더 이상 문제를 해결하는 방법을 모르겠습니다.

답변

1

로그에 따르면 당신이 호출됩니다

public void create(T entity) { 
    getEntityManager().persist(entity); 
    log.info("..persisted!"); 
} 

을 이것은 의미

  • 응용 프로그램 관리 엔티티 관리자를 사용
  • 이 작업이 엔티티 관리자에 의해 허용되는 지속
  • 엔티티는 지속성 컨텍스트에 의해 관리됩니다 (메모리 내 구조)

그러나 이는 엔티티가 데이터베이스에 기록되었음을 의미하지 않습니다. 새 트랜잭션이 시작되면 지속성 컨텍스트가 트랜잭션과 동기화됩니다. 영속 컨텍스트 (관리 엔티티)를 데이터베이스와 동기화하려면 flush 또는 commit을 호출해야합니다. PageJpaController.create이 올바르게 수행되었지만 호출 된 것 같습니다. 나는 그렇지 않다고 생각한다.

em = getEntityManager(); 
em.getTransaction().begin(); //synchronizes the persistence context with TX 
em.persist(page);    //adds page to the persistence context 
em.getTransaction().commit(); //flushes persistence context to the database 
+0

나는 당신이 무슨 뜻인지 볼 수 있지만,'AbstractFacade''에서 PageJpaController.create'를 호출하는 방법을 모르겠어요. 방법은 메서드를 재정의하는 것입니다? 모든 메소드가 오버라이드 된 경우 추상 클래스가 아닌 추상적 인 외관을 인터페이스로 만들 수 있습니다. 나는이 추상 클래스에서 generics를 사용하여 ** 의도 된 ** 컨트롤러와 메소드를 호출하는 방법을 이해하지 못한다. – Thufir

+1

Selenium에 대한 경험이 없지만 [façade] (http://en.wikipedia.org/wiki/Facade_pattern) 패턴의 경우 'AbstractFacade '이 JPAController의 기능을 대신 받아야한다고 생각합니다. 결국 추상화되고 결국에는 필요한 경우'PageFacade' 또는'LinkFacade' 클래스에서 재정의하십시오. 그런 다음'SeleniumWebPageIterator'에서 facade 메소드를 호출하면 JPA에 대한 액세스가 단순화됩니다. – wypieprz