首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么没有持久化一个新的实体?

为什么没有持久化一个新的实体?
EN

Stack Overflow用户
提问于 2012-08-04 09:12:20
回答 3查看 448关注 0票数 1

NoResultException的情况下,如何实例化和持久化Newsgroup实体?

代码语言:javascript
复制
package net.bounceme.dur.usenet.driver;

import java.util.logging.Logger;
import javax.mail.Folder;
import javax.mail.Message;
import javax.persistence.*;
import net.bounceme.dur.usenet.model.Article;
import net.bounceme.dur.usenet.model.Newsgroup;

class DatabaseUtils {

    private static final Logger LOG = Logger.getLogger(DatabaseUtils.class.getName());
    private EntityManagerFactory emf = Persistence.createEntityManagerFactory("USENETPU");
    private EntityManager em = emf.createEntityManager();

    public void persistArticle(Message message, Folder folder) {
        //do all the persistence here?
        String fullNewsgroupName = folder.getFullName();
        Newsgroup newsgroup = null;
        TypedQuery<Newsgroup> query = em.createQuery("SELECT n FROM Newsgroup n WHERE n.newsgroup = :newsGroupParam", Newsgroup.class);
        query.setParameter("newsGroupParam", fullNewsgroupName);
        try {
            newsgroup = query.getSingleResult();
            LOG.info("found " + query.getSingleResult()); //ok
        } catch (javax.persistence.NoResultException e) {
            LOG.info(e + "\ncould not find " + fullNewsgroupName); //ok
            newsgroup = new Newsgroup(folder);
            //it seems like the persist statement never executes...
            em.persist(newsgroup);
        } catch (NonUniqueResultException e) {
            LOG.info("\nshould never happen\t" + fullNewsgroupName); //not ok, should never execute
        }
        //need some mechanism to ensure that newsgroup is never a null reference
        Article article = new Article(message, newsgroup);
        em.persist(article); //never seems to execute..
    }

    public void close() {
        em.close();
        emf.close();//necessary?
    }
}

现在,似乎一次又一次,没有找到查询的结果:

代码语言:javascript
复制
run:
DEBUG: nntp: newsrc loading /home/thufir/.newsrc
DEBUG: nntp: newsrc load: 5 groups in 30ms
Aug 03, 2012 6:04:47 PM net.bounceme.dur.usenet.driver.FetchBean <init>
INFO: [gwene.com.androidcentral, gwene.com.blogspot.emacsworld, gwene.com.blogspot.googlecode, gwene.com.blogspot.googlereader, gwene.com.economist]
[EL Info]: 2012-08-03 18:04:51.277--ServerSession(28034142)--EclipseLink, version: Eclipse Persistence Services - 2.3.0.v20110604-r9504
[EL Info]: 2012-08-03 18:04:52.417--ServerSession(28034142)--file:/home/thufir/NetBeansProjects/USENET/build/classes/_USENETPU login successful
[EL Warning]: 2012-08-03 18:04:52.557--ServerSession(28034142)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'usenet.ARTICLE' doesn't exist
Error Code: 1146
Call: ALTER TABLE ARTICLE DROP FOREIGN KEY FK_ARTICLE_NEWSGROUP_ID
Query: DataModifyQuery(sql="ALTER TABLE ARTICLE DROP FOREIGN KEY FK_ARTICLE_NEWSGROUP_ID")
[EL Warning]: 2012-08-03 18:04:52.572--ServerSession(28034142)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown table 'ARTICLE'
Error Code: 1051
Call: DROP TABLE ARTICLE
Query: DataModifyQuery(sql="DROP TABLE ARTICLE")
[EL Warning]: 2012-08-03 18:04:52.65--ServerSession(28034142)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown table 'NEWSGROUP'
Error Code: 1051
Call: DROP TABLE NEWSGROUP
Query: DataModifyQuery(sql="DROP TABLE NEWSGROUP")
Aug 03, 2012 6:04:54 PM net.bounceme.dur.usenet.driver.DatabaseUtils persistArticle
INFO: javax.persistence.NoResultException: getSingleResult() did not retrieve any entities.
could not find gwene.com.androidcentral
Aug 03, 2012 6:04:54 PM net.bounceme.dur.usenet.driver.DatabaseUtils persistArticle
INFO: javax.persistence.NoResultException: getSingleResult() did not retrieve any entities.
could not find gwene.com.androidcentral
Aug 03, 2012 6:04:54 PM net.bounceme.dur.usenet.driver.DatabaseUtils persistArticle
INFO: javax.persistence.NoResultException: getSingleResult() did not retrieve any entities.
could not find gwene.com.androidcentral
Aug 03, 2012 6:04:54 PM net.bounceme.dur.usenet.driver.DatabaseUtils persistArticle
INFO: javax.persistence.NoResultException: getSingleResult() did not retrieve any entities.
could not find gwene.com.androidcentral
Aug 03, 2012 6:04:54 PM net.bounceme.dur.usenet.driver.DatabaseUtils persistArticle
INFO: javax.persistence.NoResultException: getSingleResult() did not retrieve any entities.
could not find gwene.com.androidcentral
Aug 03, 2012 6:04:54 PM net.bounceme.dur.usenet.driver.DatabaseUtils persistArticle
INFO: javax.persistence.NoResultException: getSingleResult() did not retrieve any entities.
could not find gwene.com.androidcentral
Aug 03, 2012 6:04:54 PM net.bounceme.dur.usenet.driver.DatabaseUtils persistArticle
INFO: javax.persistence.NoResultException: getSingleResult() did not retrieve any entities.
could not find gwene.com.androidcentral
Aug 03, 2012 6:04:54 PM net.bounceme.dur.usenet.driver.DatabaseUtils persistArticle
INFO: javax.persistence.NoResultException: getSingleResult() did not retrieve any entities.
could not find gwene.com.androidcentral
Aug 03, 2012 6:04:54 PM net.bounceme.dur.usenet.driver.DatabaseUtils persistArticle
INFO: javax.persistence.NoResultException: getSingleResult() did not retrieve any entities.
could not find gwene.com.blogspot.emacsworld
Aug 03, 2012 6:04:54 PM net.bounceme.dur.usenet.driver.DatabaseUtils persistArticle
INFO: javax.persistence.NoResultException: getSingleResult() did not retrieve any entities.
could not find gwene.com.blogspot.googlecode
Aug 03, 2012 6:04:54 PM net.bounceme.dur.usenet.driver.DatabaseUtils persistArticle
INFO: javax.persistence.NoResultException: getSingleResult() did not retrieve any entities.
could not find gwene.com.blogspot.googlecode
Aug 03, 2012 6:04:54 PM net.bounceme.dur.usenet.driver.DatabaseUtils persistArticle
INFO: javax.persistence.NoResultException: getSingleResult() did not retrieve any entities.
could not find gwene.com.blogspot.googlecode
Aug 03, 2012 6:04:54 PM net.bounceme.dur.usenet.driver.DatabaseUtils persistArticle
INFO: javax.persistence.NoResultException: getSingleResult() did not retrieve any entities.
could not find gwene.com.blogspot.googlecode
Aug 03, 2012 6:04:54 PM net.bounceme.dur.usenet.driver.DatabaseUtils persistArticle
INFO: javax.persistence.NoResultException: getSingleResult() did not retrieve any entities.
could not find gwene.com.blogspot.googlecode
Aug 03, 2012 6:04:54 PM net.bounceme.dur.usenet.driver.DatabaseUtils persistArticle
INFO: javax.persistence.NoResultException: getSingleResult() did not retrieve any entities.
could not find gwene.com.blogspot.googlecode
Aug 03, 2012 6:04:55 PM net.bounceme.dur.usenet.driver.DatabaseUtils persistArticle
[EL Info]: 2012-08-03 18:04:55.344--ServerSession(28034142)--file:/home/thufir/NetBeansProjects/USENET/build/classes/_USENETPU logout successful
INFO: javax.persistence.NoResultException: getSingleResult() did not retrieve any entities.
could not find gwene.com.blogspot.googlecode
Aug 03, 2012 6:04:55 PM net.bounceme.dur.usenet.driver.DatabaseUtils persistArticle
INFO: javax.persistence.NoResultException: getSingleResult() did not retrieve any entities.
could not find gwene.com.blogspot.googlecode
Aug 03, 2012 6:04:55 PM net.bounceme.dur.usenet.driver.DatabaseUtils persistArticle
INFO: javax.persistence.NoResultException: getSingleResult() did not retrieve any entities.
could not find gwene.com.economist
Aug 03, 2012 6:04:55 PM net.bounceme.dur.usenet.driver.DatabaseUtils persistArticle
INFO: javax.persistence.NoResultException: getSingleResult() did not retrieve any entities.
could not find gwene.com.economist
Aug 03, 2012 6:04:55 PM net.bounceme.dur.usenet.driver.DatabaseUtils persistArticle
INFO: javax.persistence.NoResultException: getSingleResult() did not retrieve any entities.
could not find gwene.com.economist
Aug 03, 2012 6:04:55 PM net.bounceme.dur.usenet.driver.DatabaseUtils persistArticle
INFO: javax.persistence.NoResultException: getSingleResult() did not retrieve any entities.
could not find gwene.com.economist
Aug 03, 2012 6:04:55 PM net.bounceme.dur.usenet.driver.DatabaseUtils persistArticle
INFO: javax.persistence.NoResultException: getSingleResult() did not retrieve any entities.
could not find gwene.com.economist
Aug 03, 2012 6:04:55 PM net.bounceme.dur.usenet.driver.DatabaseUtils persistArticle
INFO: javax.persistence.NoResultException: getSingleResult() did not retrieve any entities.
could not find gwene.com.economist
Aug 03, 2012 6:04:55 PM net.bounceme.dur.usenet.driver.DatabaseUtils persistArticle
INFO: javax.persistence.NoResultException: getSingleResult() did not retrieve any entities.
could not find gwene.com.economist
Aug 03, 2012 6:04:55 PM net.bounceme.dur.usenet.driver.DatabaseUtils persistArticle
INFO: javax.persistence.NoResultException: getSingleResult() did not retrieve any entities.
could not find gwene.com.economist
Aug 03, 2012 6:04:55 PM net.bounceme.dur.usenet.driver.FetchBean <init>
INFO: **************************done
BUILD SUCCESSFUL (total time: 11 seconds)

当不存在唯一的Newsgroup时,如何确保将新实体持久化到数据库?这至少是代码的目的,如果不是结果的话。

新闻组:

代码语言:javascript
复制
package net.bounceme.dur.usenet.model;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Logger;
import javax.mail.Folder;
import javax.persistence.*;

@Entity
public class Newsgroup implements Serializable {

    private static final long serialVersionUID = 1L;
    private static final Logger LOG = Logger.getLogger(Newsgroup.class.getName());
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column //@Unique @UniqueConstraint interface..?
    private String newsgroup;
    @OneToMany(mappedBy = "newsgroup", cascade = CascadeType.PERSIST)
    private Set<Article> articles = new HashSet<>();

    public Newsgroup() {
        //should not create a newsgroup without a Folder
    }

    public Newsgroup(Folder folder) {
        newsgroup = folder.getFullName();//if row already exists, then what?
        LOG.fine(newsgroup);    
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Newsgroup)) {
            return false;
        }
        Newsgroup other = (Newsgroup) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return newsgroup;
    }
}

和文章:

代码语言:javascript
复制
package net.bounceme.dur.usenet.model;

import java.io.Serializable;
import java.util.logging.Logger;
import javax.mail.Message;
import javax.persistence.*;

@Entity
public class Article implements Serializable {

    private static final long serialVersionUID = 1L;
    private static final Logger LOG = Logger.getLogger(Article.class.getName());
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column
    private int messageNumber;
    @ManyToOne(cascade = CascadeType.PERSIST)
    private Newsgroup newsgroup;

    public Article() {
    }

    public Article(Message message, Newsgroup newsgroup) {
        messageNumber = message.getMessageNumber();
        this.newsgroup = newsgroup;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Article)) {
            return false;
        }
        Article other = (Article) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "\nmessageNumber\t" + messageNumber;
    }

    public int getMessageNumber() {
        return messageNumber;
    }

    public void setMessageNumber(int messageNumber) {
        this.messageNumber = messageNumber;
    }
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-08-04 11:35:47

引用Keith & Schincariol在"Pro JPA 2“中的话:

如果事务不存在,则修改操作将抛出异常,或者更改将永远不会持久存储到数据存储中。

确保您希望持久化的与EntityManager em的交互位于事务的上下文中:

代码语言:javascript
复制
public void persistArticle(Message message, Folder folder) {
    em.getTransaction().begin();
    try {
        // your code goes here; possibly current body of persistArticle(..)

        em.getTransaction().commit();
    } catch (final RuntimeException e) {
        if (em.getTransaction().isActive()) {
            em.getTransaction().rollback();
        }

        throw e;
    }
}

您很快就会发现这是常见的样板代码。考虑使用decorator

装饰器创建一个接口,定义由DatabaseUtils.

  • Let提供的服务/方法,interface.

  • Create a DataUtilsServices (装饰器)实现该接口。它的实现将包含管理事务的代码,其中工作代码(“您的代码转到此处”)变成对DatabaseUtils.

实例上的相同方法的调用

现在,使用装饰器将"worker“从”事务服务“中分离出来,这样将来就可以轻松地进入Java EE、Spring或其他为您管理事务的容器框架。例如,包含所有样板的DatabaseUtilsServices很可能成为EJB装饰器的一部分:

代码语言:javascript
复制
@Override
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void persistArticle(Message message, Folder folder) {
    return databaseUtils.persistArticle(message, folder);
}
票数 2
EN

Stack Overflow用户

发布于 2012-08-04 15:17:24

因为JPA没有“自动提交”模式(即无事务)。事务外的操作应该延迟到下一个事务发生(而您的事务没有发生)。

显然,一些JPA实现(如DataNucleus JPA)提供了完整的自动提交功能,因为它们认为这是一个非常有用的工具,可以简化用户的工作……所以,也许你只是在使用其中一个不允许这样做的工具。

票数 2
EN

Stack Overflow用户

发布于 2012-08-04 09:57:51

也许在实例化新文章的行前插入以下行就足够了:

代码语言:javascript
复制
if (newsgroup==null) {
    newsgroup = new NewsGroup();
}

此外,如果从文章到新闻组的关系没有将其Cascade属性设置为PERSIST,则可能需要手动持久存储()新的新闻组。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11805116

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档