简体   繁体   English

使用JDBI SQL Object API同时检索或创建新行

[英]Concurrently retrieve or create new row using JDBI SQL Object API

I'm using JDBI and would like to use the SQL Object API in order to, given a field value, search if a row exists for this value, return its key if found, create it if not found and return the generated key (talking to a MySQL database). 我正在使用JDBI,并且想使用SQL Object API ,以便在给定字段值的情况下搜索该值是否存在一行,如果找到则返回其键,如果未找到则创建它并返回生成的键(到MySQL数据库)。

Is it possible to do this using SQL Object API without any stored procedure? 是否可以使用没有任何存储过程的SQL Object API来执行此操作?

There is no magic in the JDBI SQL Object API whch will do this for you. JDBI SQL Object API中没有魔术可以为您完成此操作。 You will need several SQL statements, just as you would in a stored procedure. 就像在存储过程中一样,您将需要多个SQL语句。

If you want to combine it in a single method in your DAO class, you can make it an abstract class rather than an interface, then it can have a concrete method containing the logic you need, and annotate that to make it occur within a transaction: 如果要将其合并到DAO类中的单个方法中,则可以使其成为抽象类而不是接口,然后可以使用包含所需逻辑的具体方法,并对其进行注释以使其在事务中发生:

  public abstract class MyDAO {

    @Transaction
    public long getId(String value) {
      Thing thing = findByValue(value);
      if (thing != null) {
        return thing.getId();
      } else {
        return addNewRecord(value);
      } 

    }

    @SqlQuery("select * from mytable where value = :value")
    public Thing findByValue(@Bind("value") String value);

    @SqlUpdate("insert into mytable (value) values (:value)")
    @GetGeneratedKeys
    public long addNewRecord(String value);

  }

To do this correctly, you need to handle the concurrency inside the database. 若要正确执行此操作,您需要处理数据库内部的并发。 Create the table where value is a unique index: 创建其中value是唯一索引的表:

CREATE TABLE mytable (
  id bigint NOT NULL PRIMARY KEY,
  value varchar(100) NOT NULL UNIQUE
);

You can then use MySQL's INSERT IGNORE syntax, which skips errors such as duplicate keys: 然后,您可以使用MySQL的INSERT IGNORE语法,该语法将跳过诸如重复键之类的错误:

INSERT IGNORE INTO mytable VALUES (:value);

After the insert, read the row: 插入后,读取以下行:

SELECT * FROM mytable WHERE value = :value;

If always running the extra insert is a performance concern, you can perform the read first and only insert if the record does not exist. 如果始终运行额外的插入是性能方面的考虑,则可以先执行读取,并且仅在记录不存在时才插入。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM