JPA:如何在独立 Java 应用程序中持久化后获取 Id

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10035973/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 23:20:59  来源:igfitidea点击:

JPA: How to get Id after persist in standalone java app

javajpapersistenceeclipselink

提问by Thang Pham

This is a standalone java application, not web application. So when I persist the object like this

这是一个独立的 Java 应用程序,而不是 Web 应用程序。所以当我像这样持久化对象时

public <T> T create(T t) {
    em.getTransaction().begin();
    em.persist(t);
    em.flush();
    em.getTransaction().commit();
    return t;
}

The idinside the T tobject is still null, even though a new row with correct data and id is created correctly inside the database. Usually in my web app that utilize @EJB, the idavailable right after I persist, since it persist the entity object into my persistence context, I am not sure if I have my persistence context here?

id内部T t对象仍然为空,即使新行正确的数据,ID是数据库中正确创建。通常在我的 web 应用程序中@EJBid在我持久化后立即可用,因为它将实体对象持久化到我的持久化上下文中,我不确定这里是否有我的持久化上下文?

This is how I mapped my id inside my @Entity Class

这就是我在 @Entity 类中映射我的 id 的方式

@Id
@Basic(optional = false)
@Column(name = "ID")
private Long id;

also I make the id of this table in the database AUTO_INCREMENT, like this

我也在数据库中制作了这张表的id AUTO_INCREMENT,就像这样

CREATE TABLE Config
(
    ID int NOT NULL AUTO_INCREMENT,
    PRIMARY KEY (ID)
)

This is how I obtain my EntityManager

这就是我获取 EntityManager 的方式

EntityManagerFactory emf = Persistence.createEntityManagerFactory("CorePU");
em = emf.createEntityManager();

Here is what inside my persistence.xml

这是我的 persistence.xml

<persistence-unit name="CorePU" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>    
<class>com.wf.docsys.core.model.Config</class>    
<properties>
  <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/XNINFODB"/>
  <property name="javax.persistence.jdbc.password" value="xxx"/>
  <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
  <property name="javax.persistence.jdbc.user" value="xxx"/>
</properties>

Please help, I am not sure what I did wrong here.

请帮忙,我不确定我在这里做错了什么。

采纳答案by Thang Pham

Here is my answer. Tested

这是我的答案。已测试

When mapping your Id, switch from what I have above, which is

映射您的 ID 时,从我上面的切换,即

@Id
@Basic(optional = false)
@Column(name = "ID")
private Long id;

to

@Entity
public class Person {
   @Id
   @TableGenerator(name="TABLE_GEN", table="SEQUENCE_TABLE", pkColumnName="SEQ_NAME",
       valueColumnName="SEQ_COUNT", pkColumnValue="PERSON_SEQ")
   @GeneratedValue(strategy=GenerationType.TABLE, generator="TABLE_GEN")
   private long id;
   ...
}

Since I use microsoft SQL server, I have to use @TableGenerator. More information can be found here http://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing#Table_sequencing

由于我使用 microsoft SQL 服务器,因此我必须使用@TableGenerator. 更多信息可以在这里找到http://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing#Table_sequencing

回答by barsju

Try adding a @GeneratedValueon your id field.

尝试@GeneratedValue在您的 id 字段上添加一个。

回答by Guedes

As I found on this postthe EntityManager have a method called refreshthat will update your object after you persist him.

正如我在这篇文章中发现,EntityManager 有一个叫做refresh的方法,它会在你坚持他之后更新你的对象。

So your code will probably looks like this:

所以你的代码可能看起来像这样:

public <T> T create(T t) {
    em.getTransaction().begin();
    em.persist(t);
    em.refresh(t);
    em.flush();
    em.getTransaction().commit();
    return t;
}

I haven't tested this, so I'm not sure where exactly to put the refresh method call, there, after the commit, after the flush, etc.

我还没有测试过这个,所以我不确定在哪里确切地放置刷新方法调用,在那里,在提交之后,在刷新之后等等。

Hope it can help you.

希望它可以帮助你。

Good luck.

祝你好运。

回答by Chris Hinshaw

I know it's not a persist but the merge will do the same thing more simply. I wrap my persist in an actual merge operation which will save the entity if it does not exist.

我知道这不是持久化,但合并会更简单地做同样的事情。我将我的持久性包装在一个实际的合并操作中,如果实体不存在,它将保存该实体。

public T persist(T obj) {
    EntityManager em = ThreadLocalPersistenceManager.getEntityManager();

    EntityTransaction tx = em.getTransaction();
    try {
        tx.begin();
        obj = em.merge(obj);
    } finally {
        if (! tx.getRollbackOnly()) {
            tx.commit();
        }
    }

    return obj;
}


/**
 * This will save the object and return the id of the persisted object.
 *  
 * @param obj
 * @return The id of the persisted object.
 */
public Long save(T obj) {
    persist(obj);
    return obj.getId();
}