java - JPA - 在persist()之后返回自动生成的id

我正在使用JPA(EclipseLink)和Spring。 假设我有一个带有自动生成ID的简单实体:

@Entity
public class ABC implements Serializable {
     @Id
     @GeneratedValue(strategy=GenerationType.IDENTITY)
     private int id;

     // ...
}

在我的DAO类中,我有一个insert方法,在该实体上调用persist()。 我希望该方法返回新实体的生成ID,但是当我测试它时,它返回0

public class ABCDao {
    @PersistenceContext
    EntityManager em;

    @Transactional(readOnly=false)
    public int insertABC(ABC abc) {
         em.persist(abc);
         // I WANT TO RETURN THE AUTO-GENERATED ID OF abc
         // HOW CAN I DO IT?
         return abc.id; // ???
    }
}

我还有一个包装DAO的服务类,如果这有所不同:

public class ABCService {
    @Resource(name="ABCDao")
    ABCDao abcDao;

    public int addNewABC(ABC abc) {
         return abcDao.insertABC(abc);
    }
}
sura2k asked 2019-08-13T10:30:55Z
6个解决方案
149 votes

只保证在刷新时生成ID。 坚持一个实体只会使它附加" 到持久化上下文。 因此,要么明确地刷新实体管理器:

em.persist(abc);
em.flush();
return abc.getId();

或返回实体本身而不是其ID。 当事务结束时,将发生刷新,因此事务外部的实体的用户将在实体中看到生成的ID。

@Override
public ABC addNewABC(ABC abc) {
    abcDao.insertABC(abc);
    return abc;
}
JB Nizet answered 2019-08-13T10:31:16Z
10 votes
@Entity
public class ABC implements Serializable {
     @Id
     @GeneratedValue(strategy=GenerationType.IDENTITY)
     private int id;   
}

检查实体类中是否存在@GeneratedValue表示法。这告诉JPA您的实体属性自动生成的行为

utkal patel answered 2019-08-13T10:31:41Z
3 votes

这就是我做的方式:

EntityManager entityManager = getEntityManager();
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
entityManager.persist(object);
transaction.commit();
long id = object.getId();
entityManager.close();
Koray Tugay answered 2019-08-13T10:32:00Z
2 votes

您也可以使用GenerationType.TABLE而不是IDENTITY,它仅在插入后可用。

James answered 2019-08-13T10:32:25Z
0 votes

另一个与4.0兼容的选项:

在提交更改之前,您可以从与上下文关联的集合中恢复新的getIdSnapshot()对象,如下所示:

CayenneDataObject dataObjectsCollection = (CayenneDataObject)cayenneContext.newObjects();

然后访问集合中每个的getIdSnapshot(),如:

ObjectId objectId = dataObject.getObjectId();

最后,您可以在值下进行迭代,其中通常生成的id将是getIdSnapshot()返回的Map中的第一个值(对于单个列键),它还包含与之关联的列名称。 PK作为关键字:

objectId.getIdSnapshot().values()
emecas answered 2019-08-13T10:33:12Z
-2 votes
em.persist(abc);
em.refresh(abc);
return abc;
Andrey answered 2019-08-13T10:33:30Z
translate from https://stackoverflow.com:/questions/9732453/jpa-returning-an-auto-generated-id-after-persist