我正在使用 JPA (EclipseLink) 和 Spring。假设我有一个带有自动生成 ID 的简单实体:
@Entity
public class ABC implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
// ...
}
在我的 DAO 类中,我有一个在此实体上调用 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);
}
}
ID 只保证在刷新时生成。持久化一个实体只会使其“附加”到持久化上下文。因此,要么显式刷新实体管理器:
em.persist(abc);
em.flush();
return abc.getId();
或返回实体本身而不是其 ID。当事务结束时,将发生刷新,事务外实体的用户将因此在实体中看到生成的 ID。
@Override
public ABC addNewABC(ABC abc) {
abcDao.insertABC(abc);
return abc;
}
@Entity
public class ABC implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
}
检查您的实体类中是否存在 @GeneratedValue 表示法。这会告诉 JPA 您的实体属性自动生成的行为
我是这样做的:
EntityManager entityManager = getEntityManager();
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
entityManager.persist(object);
transaction.commit();
long id = object.getId();
entityManager.close();
您还可以使用 GenerationType.TABLE 而不是 IDENTITY,后者仅在插入后可用。
与 4.0 兼容的另一个选项:
在提交更改之前,您可以从关联到上下文的集合中恢复新的 CayenneDataObject
对象,如下所示:
CayenneDataObject dataObjectsCollection = (CayenneDataObject)cayenneContext.newObjects();
然后访问集合中每个元素的 ObjectId
,例如:
ObjectId objectId = dataObject.getObjectId();
最后,您可以在值下进行迭代,通常生成的 ID 将是 getIdSnapshot()
返回的 Map 中的第一个值(对于单个列键),它还包含关联的列名以 PK 作为密钥:
objectId.getIdSnapshot().values()
我就是这样做的。你可以试试
public class ABCService {
@Resource(name="ABCDao")
ABCDao abcDao;
public int addNewABC(ABC abc) {
ABC.setId(0);
return abcDao.insertABC(abc);
}
}
em.persist(abc);
em.refresh(abc);
return abc;
em.flush()
而不是 em.refresh(abc)
。
不定期副业成功案例分享
@GeneratedValue
注释 id 字段 - 无论需要什么insertABC
会创建一个新对象吗?还是修改旧的?