在SQLite和JPA之间交替插入时重复主键

nafvub8i  于 2022-11-14  发布在  SQLite
关注(0)|答案(3)|浏览(145)

表格Section

secID INTEGER Primary Key
secname TEXT

主键SQLite将自动设置在insert上:

INSERT INTO Section(secname) VALUES("Default");

Section类:

@Entity
@Table(name="\"Section\"")
public class Section implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @Column(name="\"secID\"")
    private int secID;

    @Column(name="\"secname\"")
    private String secname;
    + Getter and Setter
}

使用SQLite我已经插入了两行。当我使用Java持久性API插入时:

Section sec = new Section();
sec.setSecname("Test2");
tx.begin();
    em.persist(sec);
tx.commit();

它会将secID设置为0。然后,当我插入另一行时,我会收到一个错误,因为这一次secID = 1已经存在,这是因为SQLite中之前的两次插入(自动递增主键会自动将secID设置为1和2)。
如何使用Java持久性API避免此问题?

dddzy1tm

dddzy1tm1#

在您的idMap上添加@GeneratedValue(strategy = GenerationType.IDENTITY)就可以了。

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="\"secID\"")
private int secID;
c3frrgcw

c3frrgcw2#

I don't think your second insert is colliding with the two values ( secID = 1 and 2) already in the table; I think it's colliding with the value you just inserted ( secID = 0).
You aren't explicitly setting secID anywhere, which means it's 0. So it's inserting 0, over and over.
Change the field secID in your class to be an Integer and not an int , and it should behave as the SQLite docs suggest , where, when "you try to insert a NULL into an INTEGER PRIMARY KEY column, the column will actually be filled with an integer that is one greater than the largest key already in the table." (Again, right now you are inserting 0, not null .)

ws51t4hk

ws51t4hk3#

加上这个以防有人在2022年及以后跌跌撞撞地进入这个。
虽然@Predrag Maric给出的答案对我很有效,但在大多数博客文章或教程中,在配置JPA和SQLite Dialect方面缺少一个步骤。我找到了解决这个问题的方法。原来SQL方言有一个极其重要的缺失函数,那就是类SQLIdentityColumnSupport中的hasDataTypeInIdentityColumn()。这是添加函数后的外观。

public class SQLiteIdentityColumnSupport extends IdentityColumnSupportImpl {
    @Override
    public boolean supportsIdentityColumns() {
        return true;
    }

    @Override
    public boolean hasDataTypeInIdentityColumn() {
        return false;
    }

    @Override
    public String getIdentitySelectString(String table, String column, int type) throws MappingException {
        return "select last_insert_rowid()";
    }

    @Override
    public String getIdentityColumnString(int type) throws MappingException {
        return "integer";
    }
}

can be found here类实现的参考。
在此之后,一旦添加GenerationType.IDENTITY作为策略,SQLite将最终处理自动递增的id,并且INSERTUPDATE操作将正常工作。

相关问题