【问题标题】:How to create a sequence in JPA without creating it directly in the database如何在 JPA 中创建序列而不直接在数据库中创建序列
【发布时间】:2016-03-23 10:40:09
【问题描述】:

我正在做一项服务,该服务从源获取数据并使用 JPA 将它们提取到我的数据库中。 id 是使用序列生成的。 我已经使用以下命令在我的数据库上创建了序列:

CREATE SEQUENCE crm_test_sq_1 MINVALUE 1 MAXVALUE 999999999999999999999999999 START WITH 1 INCREMENT BY 1 CACHE 100 NOCYCLE

但是,我不知道如何直接从我的代码中创建序列。

谁能帮我解决这个问题?非常感谢!

我的模型类,modeltest.java:

    @Entity
    @Table(name = "MODEL_TEST")
    
    @JsonPropertyOrder({ "ID", "CODE", "NAME" })
    @XmlRootElement
    @NamedQueries({
        @NamedQuery(name = "modeltest.getall", query = "SELECT e FROM modelteste"),
        @NamedQuery(name = "modeltest.deleteAll", query = "DELETE FROM modeltest e")})
    public class modeltest implements Serializable {
        private static final long serialVersionUID = 1L;
    
        @Id
        @GeneratedValue(generator = "crm_test_sq", strategy = GenerationType.SEQUENCE)
        @SequenceGenerator(name = "crm_test_sq", sequenceName = "crm_test_sq",allocationSize=1)
        @Column(name="ID", unique=true, nullable=false, precision=10, scale=0)
        private Long id;
    
        @Column(name = "CODE")
        private String isocurrencycode;
    
        @Column(name = "NAME")
        private String currencyname;
    
        public modeltest() {
        }
//........... getter and setter method

我的 dao 类,modeltestDao.java

public Boolean saveData() {
        
        
//............................................
            getEntityManager().createNamedQuery("modeltest.deleteAll").executeUpdate();
            
            // i want something like below, but obviously this line of code give me an error
            getEntityManager().createNativeQuery ("CREATE SEQUENCE crm_test_sq_1 MINVALUE 1 MAXVALUE 999999999999999999999999999 START WITH 1 INCREMENT BY 1 CACHE 100 NOCYCLE").executeUpdate();
            
        /....................
        return true;
    }

编辑:顺便说一句,为什么我想重置序列是每次我运行服务(将数据提取到数据库中)时,唯一标识符增加了 1。例如,我第一次运行数据时,id 以 1 开头并以 10 结尾,我第二次运行数据时,id 以 11 开头并以 20 结尾。这个问题只有在我重新启动服务器时才会停止。

For example:
call saveData() first time
DATA IN TABLE:
ID 1 2 3 4 5
call saveData() second time
DATA IN TABLE:
ID 6 7 8 9 10

其他数据不变,但id。所以我找到解决这个问题的方法是每次运行 saveData() 时删除并重新创建序列

【问题讨论】:

  • 旁注:我建议使用 Liquibase 之类的工具来维护 db 模式。 Liquibase 支持序列。 Liquibase 等工具允许您使用重命名列而不丢失列中的数据。 JPA 通常只能帮助您初始创建 db 表。
  • 旁注 2 (JsonPropertyOrder):通常不建议将 JPA 实体导出到外部客户端,如果这是您希望通过 JsonPropertyOrder 注释实现的目标。原因:恶意客户端可能会篡改数据库主键。最好只公开业务密钥,而不是技术 ID。
  • 感谢您回答我的帖子,我想要做的是删除序列并在每次运行函数 saveData() 时重新创建它(我这样做的原因是因为我避免缓存 ID在数据库上)。因此我需要将我的序列的创建和删除命令粘贴在我的代码上。希望你明白我的意思
  • JPA 应该通过作为 JPA 2.1 一部分的模式创建工具自己创建该序列。为什么要自己做???我使用的实现将在运行时自动创建它,如果它需要在数据存储中创建实体的实例并且它发现序列不存在。
  • @NeilStockton 谢谢你,尼尔,请看我的编辑

标签: java database oracle hibernate jpa


【解决方案1】:

您的提案中有一种代码味道。为什么首先需要避免对序列进行数据库缓存?序列的全部意义在于生成唯一标识符,因此您不应在应用程序运行时重新创建序列。

如果您在该方法中创建序列,想象一下当该方法被多个线程并发调用时会发生什么。

如果您的用例有效,并且您确实需要删除所有这些记录并重置序列,并且您使用的是 Oracle 12c,则可以执行以下操作:

entityManager.createNativeQuery(
    "ALTER SEQUENCE crm_test_sq_1 RESTART START WITH 1")
.executeUpdate();

【讨论】:

  • 嗨,我试过你的代码,买它给我一个错误:“org.hibernate.util.JDBCExceptionReporter: ORA-02286: no options specified for ALTER SEQUENCE”。
  • 顺便说一句,为什么我想重置序列是每次我运行服务(将数据提取到数据库)时,唯一标识符增加了 1。例如,我第一次运行数据时,id从 1 开始以 10 结束,我第二次运行数据时,id 以 11 开始并以 20 结束。这个问题只有在我重新启动服务器时才会停止。
  • 谢谢,我找到了解决办法,createNativeQuery() 可以用来创建序列。
猜你喜欢
  • 2020-08-23
  • 2018-08-09
  • 1970-01-01
  • 1970-01-01
  • 2017-03-20
  • 2019-04-02
  • 2019-01-17
  • 2012-03-20
  • 2019-01-25
相关资源
最近更新 更多