2015-04-30 57 views
2

我遇到以下问题: 加载“HtmlPage”对象时,集合“标记”始终为大小0.集合“参数”工作正常。数据库也有正确的(我猜)条目。JPA未加载继承集合

这里是我的课:

@IdClass(HtmlPageID.class) 
@Entity 
public class HtmlPage implements Serializable { 


    /** 
    * The parameters of this HTML page. (e.g. www.google.com/#q=test&tbas=0 
    * will result in: q=test; tbase=0) 
    */ 
    @OneToMany(mappedBy = "page", cascade = CascadeType.ALL, fetch = FetchType.EAGER) 
    private LinkedList<HttpParam> parameter; 
    /** 
    * A Collection of all HTML tags. 
    */ 
    @OneToMany(mappedBy = "htmlPage", cascade = CascadeType.ALL, fetch = FetchType.LAZY) 
    private List<WebsiteTag> tags; 

} 

@IdClass(WebsiteTagID.class) 
@Entity 
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) 
public abstract class WebsiteTag implements Serializable { 


    /** 
    * The name of the tag (e.g. div for the DIV tag). 
    */ 
    @Id 
    @Column(length = 2048) 
    protected String tagName; 
    /** 
    * The associated HTML page. 
    */ 
    @Id 
    @ManyToOne 
    protected HtmlPage htmlPage; 
} 

如果我使用“@MappedSuperclass”在抽象类(我应该)我得到以下异常: 在主键字段或属性的名称主键类[null]和实体bean类[class website.WebsiteTag]必须对应,且它们的类型必须相同。另外,请确保已为XML中的相应属性指定了ID元素,并且/或者在实体类的相应字段或属性中指定了@Id。

public class WebsiteTagID implements Serializable { 

    /** 
    * The name of the tag (e.g. div for the DIV tag). 
    */ 
    @Id 
    @Column(length = 2048) 
    protected String tagName; 
    /** 
    * The associated HTML page. 
    */ 
    @Id 
    @ManyToOne 
    protected HtmlPageID htmlPage; } 

下面是我的数据库中的一些条目:

HTMLPAGE

COMPLETEPATH | STATUS | URL /s/ref = nb_sb_noss/field-keywords = smartphone |感染| www.amazon.com

WEBSITETAG

[清空]我想这不应该如此??

IFRMAETAG

TAGNAME | STATUS | COMPLETEPATH |网址
EMPTY 0.765217383991997 |感染|/s/ref = nb_sb_noss/field-keywords =智能手机| www.amazon.com


这是一个JPA查询。如果我执行这个,我会得到我期待的结果。但它不会添加到收藏中。

[EL Finest]: query: 2015-04-30 16:28:57.834--ServerSession(23649981)--Thread(Thread[main,5,main])--Execute query ReadAllQuery(name="tags" referenceClass=WebsiteTag sql="SELECT TAGNAME, STATUS, COMPLETEPATH, URL FROM WEBSITETAG WHERE ((URL = ?) AND ((STATUS = ?) AND (COMPLETEPATH = ?)))") 
    [EL Finest]: query: 2015-04-30 16:28:57.844--ServerSession(23649981)--Thread(Thread[main,5,main])--Execute query ReadAllQuery(name="tags" referenceClass=WebsiteTag) 
    [EL Finest]: connection: 2015-04-30 16:28:57.844--ServerSession(23649981)--Connection(5106948)--Thread(Thread[main,5,main])--Connection acquired from connection pool [default]. 
    [EL Fine]: sql: 2015-04-30 16:28:57.844--ServerSession(23649981)--Connection(5106948)--Thread(Thread[main,5,main])--SELECT TAGNAME, HREF, INLINKS, ISEXTERNAL, ISJAVASCRIPT, STATUS, COMPLETEPATH, URL FROM HYPERLINKTAG WHERE ((URL = ?) AND ((COMPLETEPATH = ?) AND (STATUS = ?))) 
     bind => [www.amazon.com, INFECTED, /s/ref=nb_sb_noss/field-keywords=smartphone] 

    [EL Finest]: connection: 2015-04-30 16:28:57.854--ServerSession(23649981)--Connection(5106948)--Thread(Thread[main,5,main])--Connection released to connection pool [default]. 
    [EL Finest]: query: 2015-04-30 16:28:57.854--ServerSession(23649981)--Thread(Thread[main,5,main])--Execute query ReadAllQuery(name="tags" referenceClass=WebsiteTag) 
    [EL Finest]: connection: 2015-04-30 16:28:57.854--ServerSession(23649981)--Connection(5106948)--Thread(Thread[main,5,main])--Connection acquired from connection pool [default]. 
    [EL Fine]: sql: 2015-04-30 16:28:57.864--ServerSession(23649981)--Connection(5106948)--Thread(Thread[main,5,main])--SELECT TAGNAME, HEIGHT, HEIGHTINP, INLINKS, ISEXTERNAL, ISJAVASCRIPT, SRC, WIDTH, WIDTHINP, STATUS, COMPLETEPATH, URL FROM IFRAMETAG WHERE ((URL 
= ?) AND ((COMPLETEPATH = ?) AND (STATUS = ?))) 
     bind => [www.amazon.com, INFECTED, /s/ref=nb_sb_noss/field-keywords=smartphone] 

我真的没有想法如何解决这个问题。提前致谢!

编辑1

这里一些示例代码,我如何管理我的收藏:

public HtmlPage extracHtmlpage(Webpage page, String path, String htmlCode) throws MalformedURLException, UnsupportedEncodingException { 
     HtmlPage htmlPage = new HtmlPage(page, path, null, null) 

     /* Extract the GET Params */ 
     // If there is one '=' we know that there is at least one GET parameter with a value. 
     if (path.contains("=")) { 
      htmlPage.setParameter(this.extractGetParams(htmlPage, path)); 
     } 
     /* Handle all the HTML tags.*/ 
     htmlPage.setTags(this.extractHtmlElements(htmlPage, htmlCode)); 
     htmlPage.setCompletePath(new URL(corrPath).getPath()); 
     return (htmlPage); 
    } 

private List<WebsiteTag> extractHtmlElements(HtmlPage htmlPage, String htmlCode) { 
    List<WebsiteTag> tags = new LinkedList<>(); 
    LinkedList<HyperLinkTag> links = new LinkedList<>(); 
    LinkedList<IFrameTag> iFrames = new LinkedList<>(); 
    //Loop over all the html elements 
    Document doc = Jsoup.parse(htmlCode); 
    /*Handle links*/ 
    Elements rawLinks = doc.select("a"); 
    for (Element link : rawLinks) { 
     HyperLinkTag ref = new HyperLinkTag(link.attr("href"), htmlPage); 
      links.add(ref); 

    } 
    tags.addAll(links); 
    /*Handle iframes*/ 
    Elements rawIFrames = doc.select("iframe"); 
    for (Element iFrame : rawIFrames) { 
     IFrameTag tag = this.extractIFrameTag(iFrame, htmlPage); 
     iFrames.add(tag); 
    } 
    tags.addAll(iFrames); 
    return (tags); 
} 

最后:

private IFrameTag extractIFrameTag(Element iFrame, HtmlPage page) { 
     String width = iFrame.attr("width").replace("%", "").replace("px", ""); 
     boolean wP = iFrame.attr("width").contains("%"); 
     String height = iFrame.attr("height").replace("%", "").replace("px", ""); 
     boolean hP = iFrame.attr("height").contains("%"); 
     String src = iFrame.attr("src"); 

     IFrameTag tag = new IFrameTag(new Integer(width), wP, 
       new Integer(height),hP, src, page); 
     return (tag); 
} 

我没有看到在这一点上这种迁徙是不一致的istent。

EDIT 2

我的DAO代码是相当直截了当

public void commitWebpage(HtmlPage page) { 
     EntityTransaction tx = em.getTransaction(); 
     tx.begin(); 
     em.persist(page); 
     tx.commit(); 
} 

public void updateHtmlPage(HtmlPage page) { 
    EntityTransaction tx = em.getTransaction(); 
    tx.begin(); 
    em.merge(page); 
    tx.commit();  
} 

我坚持/更新这样的:

HtmlPage webpage = this.extracHtmlpage(page, path, htmlCode) 
    insertData(webpage); 

插入代码

public void insertData(HtmlPage website) { 
    WebpageDAO dao = new WebpageDAO(); 
    if (dao.getWebpage(website) == null) { 
     dao.commitWebpage(website); 
    } else { 
     dao.updateHtmlPage(website); 
    } 
} 

是什么不工作我s:

EntityManagerFactory emf = Persistence.createEntityManagerFactory("TestDataPU"); 
EntityManager em = emf.createEntityManager(); 
EntityTransaction tx = em.getTransaction(); 
tx.begin(); 
Query query = em.createQuery("SELECT w FROM Webpage w"); 
List<Webpage> results = (List<Webpage>) query.getResultList(); 
tx.commit(); 

在“结果”中,我得到了我的HtmlPages(yeah!)集合“参数”在那里,并且具有正确的值。但收集“标签”的大小为0(buh!)。当我坚持它时,HTMLPages具有“标签”。

+0

您不能将WebsiteTag标记为mappedSuperclass,然后使用OneToMany映射到它,因为mappedSuperclass不是实体。它只是一堆从JPA角度完全无关的子类继承的映射。如果你想映射它,它需要是一个实体及其子类通过JPA继承相关。 – Chris

+0

另外,映射集合不能是LinkedList类型。您必须使用接口:列表。 –

回答

0

需要更多的信息才能真正了解发生了什么问题,但我认为您对某些关键点做出了一些错误的假设,这些假设可能会导致您期望出现不同的(但是错误的)行为。

首先,mappedsuperclass只是一种将一些通用映射映射到父项以便可以重用的方法。任何从映射超类扩展的实体之间确实没有任何关系(从JPA /数据库的角度来看),所以实际上没有办法映射到映射超类;它只是不是一个实体。

现在到每班继承。这意味着继承层次结构中的每个实体都将拥有自己的表,其中包含该类存在的实例所需的所有字段。由于WebsiteTag是抽象的,WEBSITETAG本身不应该有任何数据 - 甚至不需要存在。 WebsiteTag的任何子类都将拥有其自己的表,其中包含与WEBSITETAG相同的所有字段以及它们可能扩展的任何父实体类,以及用于其他映射的所有字段。这个继承模型中的实体实例在其对应的表中只有一行。这不同于联合表继承,其中IfrmaeTag实体实例在WEBSITETAG表中有一行,IFRMAETAG中有一行,IFRMAETAG表只包含WEBSITETAG表中不包含的字段/数据。如果您希望数据存在于WEBSITETAG表中,也许这就是您应该关注的继承策略。

至于JPA查询返回的数据,但HtmlPage.tags集合是空的:这在双向关系中很常见,因为应用程序仅对关系的一侧进行更改。 JPA有一个缓存,并且在进行更改时,这些纯java对象不会自动调整。当您创建WebsiteTag并设置其htmlPage时,您还需要将该WebsiteTag添加到HtmlPage的标签列表中。如果不这样做,除非强制HtmlPage从数据库重新加载 - 集刷新,清除缓存或重新启动服务器,否则集合将不会显示此更改。维护你的集合通常效率更高,但如果需要,你可以调用em.refresh(htmlPage)。

+0

我现在正在使用Lists对象。哪些不会改变任何东西。抽象类是一个普通的实体。在那里买我的问题。我也很确定,我的HtmlPage对象是consitent。 –

+0

我不确定您的意思是“我正在使用列表对象”。你有没有尝试调用em.refresh(htmlPage),然后检查你的列表是否填充? – Chris

+0

Ps我的前两段并不是针对您的具体问题,而是针对您帖子中可见的其他一些问题和项目。具体来说,您的问题是WEBSITETAG表中是否应该有数据。 – Chris