来自Pro JPA的示例:
@Stateless
public class AuditServiceBean implements AuditService {
@PersistenceContext(unitName = "EmployeeService")
EntityManager em;
public void logTransaction(int empId, String action) {
// verify employee number is valid
if (em.find(Employee.class, empId) == null) {
throw new IllegalArgumentException("Unknown employee id");
}
LogRecord lr = new LogRecord(empId, action);
em.persist(lr);
}
}
@Stateless
public class EmployeeServiceBean implements EmployeeService {
@PersistenceContext(unitName = "EmployeeService")
EntityManager em;
@EJB
AuditService audit;
public void createEmployee(Employee emp) {
em.persist(emp);
audit.logTransaction(emp.getId(), "created employee");
}
// ...
}
文字:
即使新创建的Employee尚未在数据库中, 审计Bean可以找到该实体并验证其存在。这有效 因为这两个bean实际上共享相同的持久性 上下文。
据我了解,Id是由数据库生成的。那么,如果尚未提交事务并且尚未生成ID,如何将emp.getId()传递到audit.logTransaction()中?
答案 0 :(得分:0)
这取决于GeneratedValue的策略。如果您使用诸如Sequence或Table策略之类的东西。通常,持久性提供程序会在调用persist方法后立即将ID分配给实体(它会根据分配大小保留一些ID)。
但是,如果您使用IDENTITY策略ID,则其他提供商可能会采取不同的行动。例如在休眠模式下,如果您使用身份策略,它将立即执行插入语句并填充实体的id字段。
https://thoughts-on-java.org/jpa-generate-primary-keys/说:
休眠需要每个管理实体的主键值,并且 因此必须立即执行插入语句。
但是在eclipselink中,如果您使用IDENTITY策略,则ID将在刷新后分配。因此,如果您将冲洗模式设置为自动(或调用冲洗方法),则在持久化后将具有id。
https://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Entities/Ids/GeneratedValue说:
使用IDENTITY和其他ID生成之间有区别 策略:只有等到 发生插入-是插入操作导致了 标识符生成。由于实体的插入是 通常将其推迟到提交时间之前,标识符不会 在刷新或提交交易之前可用。
在实现中,UnitOfWorkChangeSet具有新实体的集合,这些实体在插入之前将没有真实身份。
// This collection holds the new objects which will have no real identity until inserted.
protected Map<Class, Map<ObjectChangeSet, ObjectChangeSet>> newObjectChangeSets;
JPA - Returning an auto generated id after persist()是一个与eclipselink相关的问题。
https://forum.hibernate.org/viewtopic.php?p=2384011#p2384011
有个优点我基本上是指Java Persistence中的一些言论, 冬眠。 Hibernate的API保证在调用save()之后 实体具有分配的数据库标识符。取决于ID 生成器类型,这意味着Hibernate可能必须发出INSERT 调用flush()或commit()之前的语句。这可能导致 回滚时出现问题。页面上有关于此的讨论 Hibernate的Java持久性490。
在JPA中,persist()不返回数据库标识符。为了那个原因 原因是可以想象实现会阻碍 标识符的生成,直到刷新或提交时间为止。
您的方法目前可能行之有效,但您可能会遇到麻烦 更改ID生成器或JPA实现时(从 休眠到其他事物)。
也许这对您来说不是问题,但我只是想提出来。