使用 JPA 获取最后插入记录的主键
Posted
技术标签:
【中文标题】使用 JPA 获取最后插入记录的主键【英文标题】:get primary key of last inserted record with JPA 【发布时间】:2012-10-04 02:01:18 【问题描述】:我一直在使用 JPA 将实体插入数据库,但遇到了一个问题,我需要进行插入并获取最后插入的记录的主键。
使用 PostgreSQL,我会使用返回记录 id 的 INSERT RETURNING 语句,但是在执行所有这些操作的实体管理器中,我知道的唯一方法是使用 SELECT CURRVAL。
所以问题就变成了,我有几个数据源通过 OpenMQ 将数据发送到消息驱动的 bean(通常每个源一次发送 10-100 条消息),在这个 MDB 中,我通过实体管理器将其保存到 PostgreSQL。正是在这一点上我认为会有这么多插入的“类似竞争条件”的效果,我不一定会使用 SELECT CURRVAL 获得最后一条记录 id。
我的 MDB 通过如下所示的实体管理器保留 3 个实体 bean。
非常感谢任何有关如何更好地做到这一点的帮助。
public void onMessage(Message msg)
Integer agPK = 0;
Integer scanPK = 0;
Integer lookPK = 0;
Iterator iter = null;
List<Ag> agKeys = null;
List<Scan> scanKeys = null;
try
iag = (IAgBean) (new InitialContext()).lookup(
"java:comp/env/ejb/AgBean");
TextMessage tmsg = (TextMessage) msg;
// insert this into table only if doesn't exists
Ag ag = new Ag(msg.getStringProperty("name"));
agKeys = (List) (iag.getPKs(ag));
iter = agKeys.iterator();
if (iter.hasNext())
agPK = ((Ag) iter.next()).getId();
else
// no PK found so not in dbase, insert new
iag.addAg(ag);
agKeys = (List) (iag.getPKs(ag));
iter = agKeys.iterator();
if (iter.hasNext())
agPK = ((Ag) iter.next()).getId();
// insert this into table always
iscan = (IScanBean) (new InitialContext()).lookup(
"java:comp/env/ejb/ScanBean");
Scan scan = new Scan();
scan.setName(msg.getStringProperty("name"));
scan.setCode(msg.getIntProperty("code"));
iscan.addScan(scan);
scanKeys = (List) iscan.getPKs(scan);
iter = scanKeys.iterator();
if (iter.hasNext())
scanPK = ((Scan) iter.next()).getId();
// insert into this table the two primary keys above
ilook = (ILookBean) (new InitialContext()).lookup(
"java:comp/env/ejb/LookBean");
Look look = new Look();
if (agPK.intValue() != 0 && scanPK.intValue() != 0)
look.setAgId(agPK);
look.setScanId(scanPK);
ilook.addLook(look);
// ...
【问题讨论】:
在插入新记录之前使用 SELECT nextval()。 我刚刚发现该实体实际上是在 flush() 之后使用 seq val 填充 pk,它似乎正在工作。尝试 em.persist(r); em.flush(); r.getId(); @DondiMichaelStroma 呃,没有。nextval()
推进序列。如果您这样做,您将获得一个不会分配给任何记录的 ID。
@CraigRinger 重点是自己将其分配给记录。
@DondiMichaelStroma 好的,我明白了。但是,除非您删除映射上的 @GeneratedValue
注释,否则这样做会以有趣的方式破坏事情。让 JPA 将@GeneratedValue
与IDENTITY
方案一起使用,或者与@SequenceGenerator
和SEQUENCE
方案一起使用会更好。
【参考方案1】:
JPA 规范要求在持久化之后,如果正在使用 ID 生成策略,则使用有效 ID 填充实体。您无需执行任何操作。
【讨论】:
以上是关于使用 JPA 获取最后插入记录的主键的主要内容,如果未能解决你的问题,请参考以下文章
MySQL:在没有 auto_increment 的情况下获取最后插入的主键
mysql insert一条记录后怎样返回创建记录的主键id,last