【问题标题】:ORA_02201 Sequence is not allowed hereORA_02201 此处不允许序列
【发布时间】:2021-11-07 13:02:13
【问题描述】:

希望你们一切都好。当我尝试使用 JSON 将新条目发布到数据库时,我不断收到“ORA_02201 - 此处不允许序列”SQL 语法错误。我正在使用 Oracle 自治数据库 在 Oracle 数据库中,人们使用 GenerationType.SEQUENCE 策略来增加 ID(主键)。

我之前尝试了一些东西,让我分享给你。问题的根源似乎是 Sequence 无法与 JSON 一起使用,或者没有设置为可以使用。当我的 JSON 请求没有 id 时,它会给出“此处不允许序列”,因此当序列应该工作时。 请注意,我将此应用程序作为 MVC Web 应用程序,通过从 jsp 页面中的表单输入获取数据,我将实体保存到数据库中。它可以完美运行并正确生成 ID。我相信 JSON 有问题。

{
    "firstName" : "Mark",
    "lastName" : "Heiberg",
    "email" : "heibergmark@dot.com"
}

我通过在 JSON 中指定数据库中存在的 ID 来提出请求,然后它更新了条目。所以我确信原因的根源是 id 生成,当它应该创建新的 id 时,它不起作用。我在 Internet 上找不到任何关于 JSON-Oracle DB 关系的信息。我想在这里问一下,也许你知道我可以或应该做些什么来在 JSON 请求的那一刻启用对序列生成类型的支持。提前致谢。

@PostMapping("/customers")
    Customer addCustomer(@RequestBody Customer customer){
        customer.setId(0); //set id to 0 to force it to  add customer to DB, instead of updating current.
        customerService.saveCustomer(customer);
        return customer;
    }

这是表定义SQL:(我是使用Oracle APEX环境构建的,不要介意9999999999999999,这是默认的)

CREATE TABLE  "CUSTOMER" 
   (    "ID" NUMBER(3,0) GENERATED BY DEFAULT AS IDENTITY MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER  NOCYCLE  NOKEEP  NOSCALE  NOT NULL ENABLE, 
    "FIRST_NAME" VARCHAR2(15) COLLATE "USING_NLS_COMP", 
    "LAST_NAME" VARCHAR2(15) COLLATE "USING_NLS_COMP", 
    "EMAIL" VARCHAR2(30) COLLATE "USING_NLS_COMP", 
     CONSTRAINT "CUSTOMER_PK" PRIMARY KEY ("ID")
  USING INDEX  ENABLE
   )  DEFAULT COLLATION "USING_NLS_COMP"
/

CREATE OR REPLACE EDITIONABLE TRIGGER  "BI_CUSTOMER" 
  before insert on "CUSTOMER"               
  for each row  
begin   
  if :NEW."ID" is null then 
    select "CUSTOMER_SEQ".nextval into :NEW."ID" from sys.dual; 
  end if; 
end; 

/
ALTER TRIGGER  "BI_CUSTOMER" ENABLE
/

这是我实现数据库注释的实体类:

package com.customer_tracker.entity;

import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

@Entity
@Table(name = "CUSTOMER")
public class Customer {

    public Customer() {
    }

    public Customer(String firstName, String lastName, String email) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = email;
    }

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "Customer_SEQ")
    @SequenceGenerator(name = "Customer_SEQ", sequenceName = "CUSTOMER_SEQ", allocationSize = 1)
    @Column(name = "ID")
    private int id;

    @NotNull(message = "This field is required!")
    @Size(min = 3, max = 15, message = "Write something!")
    @Column(name = "FIRST_NAME")
    private String firstName;

    @NotNull(message = "This field is required!")
    @Size(min = 3, max = 15, message = "Write something!")
    @Column(name = "LAST_NAME")
    private String lastName;

    @NotNull(message = "This field is required!")
    @Size(min = 3, max = 30, message = "Write something!")
    @Column(name = "EMAIL")
    private String email;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName.trim().replaceAll("\\s", "");
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName.trim().replaceAll("\\s", "");
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email.trim().replaceAll("\\s", "");
    }

    @Override
    public String toString() {
        return "id = " + id +
                ", firstName = " + firstName + ", lastName = " + lastName + ", email = " + email;
    }
}

这是 Hibernate 将条目保存到数据库的代码 sn-p:

package com.customer_tracker.dao;

import com.customer_tracker.entity.Customer;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public class CustomerList implements CustomerDAO{

    @Autowired
    private SessionFactory sessionFactory;

    @Override
    public void saveCustomer(Customer customer) {
        Session session = sessionFactory.getCurrentSession();
        session.saveOrUpdate(customer);
    }

}

...GETPUTDELETE 方法按预期工作,只有 POST 不起作用,因为数据库应该在幕后生成 id。

【问题讨论】:

  • 可以提供表格的ddl吗??
  • 我认为您应该尝试找到导致问题的确切 SQL 查询。
  • 我们也需要您的实体代码。
  • @RobertoHernandez 你好,我已经在线程中添加了它。感谢您的帮助。
  • 你好@JoãoDias 我已经添加了,谢谢。

标签: java json spring oracle


【解决方案1】:

问题是您使用带有选项generated alwaysidentity column,但同时您使用触发器以序列填充列ID。您不能这样做,要么使用序列和触发器,要么使用标识列。如果您使用的是 Oracle 12c 或更高版本,我强烈建议您使用标识列,除非它们继承的某些限制可能会影响您的应用程序的行为方式。

看这个例子

SQL> create table test_col ( c1 number generated always as identity start with 1 increment by 1 , c2 varchar2(1) ) ;

Table created.

SQL> insert into test_col ( c2 ) values ( 'A' ) ;

1 row created.

SQL> select * from test_col ;

        C1 C
---------- -
         1 A

SQL> insert into test_col ( c1,c2 ) values ( 2,'B' ) ;
insert into test_col ( c1,c2 ) values ( 2,'B' )
                       *
ERROR at line 1:
ORA-32795: cannot insert into a generated always identity column

您必须删除触发器和序列,因为它们在这种情况下无用。触发触发器时肯定会引发错误。当您使用标识列时,Oracle 会自动为您处理序列和插入。

标识列受以下限制:

  • 每个表都有一个且只有一个标识列。
  • 标识列的数据类型必须是数字数据类型。用户定义的数据类型不允许与标识子句一起使用。
  • CREATE TABLE AS SELECT 语句不继承标识列。
  • 标识列不能有另一个 DEFAULT 约束。
  • 可以推断加密身份列的加密算法,因此您应该使用强加密算法。
  • 标识列的内联约束不得与标识子句声明的 NOT NULL 和 NOT DEFERRABLE 约束冲突。

generated always身份列 的选项之一。在下面的链接中了解更多信息

Identity Columns

【讨论】:

  • 我在一个月前开始构建项目时尝试使用 Identity Column,因为我的讲师正在使用 MySQL Lite 和 IdentityColumn,但这对我不起作用(我的意思是我设置了 GenerationType.IDENTITY 和应用程序导致错误),所以我研究了一些关于使用 oracle 的内容并决定设置序列,相同的序列在我的 MVC Web 应用程序中工作,我从 html 表单获取数据,但不适用于 JSON 请求。
  • @fuadik88,那么我不明白您将数据模型与带有标识列的表放在一起,然后是尝试填充标识列的触发器。
  • 看来我必须深入研究数据库。
  • 禁用或删除触发器,然后重试。触发器触发了错误
  • 解决了它,看起来身份列在 ORM(JPA,Hibernate)中存在问题,所以我放弃了身份并设置了新的序列,它工作得很好。谢谢。
【解决方案2】:

如果您使用 JPA,您应该在 id 字段上添加 @Id 和 @GeneratedValue(使用适当的策略)注释,它将自动生成。

示例:https://spring.io/guides/gs/accessing-data-jpa/

【讨论】:

  • 嗨,我有这个应用程序的基于 MVC 的版本,它运行完美,从 html 表单获取输入(名字、姓氏、电子邮件)并通过生成 ID 将其保存到数据库。我设置了@Id@GeneratedValue。 JSON请求中出现了问题,它基本上说“此处不允许序列”,我怀疑是否应该添加一些注释或某种“支持”以使其与JSON一起使用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-31
  • 1970-01-01
  • 2015-07-16
相关资源
最近更新 更多