【问题标题】:Trying Derived Identifiers using @JoinedColumns, got error Attempt to modify an identity column使用 @JoinedColumns 尝试派生标识符,出现错误尝试修改标识列
【发布时间】:2013-04-10 13:09:27
【问题描述】:

这是我的sql表结构:

create table TBL_EMPLOYEE_FIVE(
    EMP_ID integer generated always as identity(start with 50, increment by 4),
    NAME varchar(50),
    COUNTRY varchar(50),
    MGR_ID integer,
    MGR_COUNTRY varchar(50),
    constraint PK_COMPOSIT_001AD primary key(EMP_ID,COUNTRY),
    constraint  FK_COMPO_00123 foreign key(MGR_ID,MGR_COUNTRY) references TBL_EMPLOYEE_FIVE
)

这是我的实体映射:

@Entity
@Table(name="TBL_EMPLOYEE_FIVE")
@IdClass(EmployeeId.class)
public class EmployeeOne implements Serializable{

    public EmployeeOne(){}
    public EmployeeOne(String employeeName,String empCountry){
        this.empCountry = empCountry;
        this.employeeName = employeeName;
    }

    public EmployeeOne(String employeeName,String empCountry,EmployeeOne manager){
        this.empCountry = empCountry;
        this.employeeName = employeeName;
        this.manager = manager;
    }

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="EMP_ID")
    private Integer employeeId;

    @Id
    @Column(name="COUNTRY")
    private String empCountry;

    @Column(name="NAME")
    private String employeeName;

    @ManyToOne( cascade= {CascadeType.PERSIST, CascadeType.PERSIST},
            fetch= FetchType.LAZY,
            targetEntity=EmployeeOne.class)
            @JoinColumns({
            @JoinColumn(name="MGR_ID",referencedColumnName="EMP_ID"),
            @JoinColumn(name="MGR_COUNTRY",referencedColumnName="COUNTRY")
    })
    private EmployeeOne manager;

    @OneToMany(cascade={CascadeType.PERSIST, CascadeType.PERSIST},mappedBy="manager")
    private Set<EmployeeOne> employees;
// getters and setters,
}

这是嵌入的 id 映射,

@Embeddable
public class EmployeeId implements Serializable{

    public EmployeeId(){}

    public EmployeeId(Integer employeeId,String empCountry){
       this.employeeId = employeeId;
       this.empCountry = empCountry;
    }

    @Column(name="EMP_ID")
    private Integer employeeId;

    @Column(name="COUNTRY")
    private String empCountry;
// only getters and implementation of hashcode and equals method
}

这就是我试图在我的主要方法中运行的:

EmployeeOne manager = new EmployeeOne("Yousuf Ahmadinejad", "IRAN");
em.persist(manager);

但在这里我遇到了一个例外,即

Caused by: javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: Attempt to modify an identity column 'EMP_ID'. 

我不是不理解异常,

但是为什么首先会出现这个异常呢?我已经用 @GenerateValue 为 Empid 注释了它,我没有手动设置 empId。是否发生此异常是因为我将主键组合为 empId 和国家/地区,而 empId 是使用 Identity 自动生成的,因此它给出了异常?

你能告诉我怎么回事

我想在这里添加的另一件事是,如果我删除了 EmployeeId.java 的 @Column 和 @Embeddeble 注释,然后运行,我得到以下异常,

Caused by: org.hibernate.PropertyAccessException: could not set a field value by reflection setter of com.entities.derived.EmployeeId.employeeId

所以只是试图找到解决方案,让员工保持自动生成的 ID 不变

【问题讨论】:

  • 不确定,但在主类和嵌入类中都指定 EMP_ID 似乎很奇怪。如果您使用 hibernate 对数据库中的实体进行逆向工程,也许这可以让您了解如何映射它?
  • 实际上我编辑了创建表查询,我从 emp_id 属性中删除了标识,并且我对实体进行了相同的更改,但我还添加了一个使用 @PrePersist 注释的方法。此方法有一个 JPQL 查询来获取员工的最大值,然后增加计数并将其设置在 employeeId 的设置器中,然后它就起作用了。但是这个解决方案是手动的,也不可行。我想要一个好的解决方案,这样我就不必删除身份了。

标签: java hibernate jakarta-ee jpa jpa-2.0


【解决方案1】:

First Hibernate 不会为复合键生成 id,因此您应该将 EmployeeOne 更改为:

@Id
//@GeneratedValue(strategy=GenerationType.IDENTITY) remove this line
@Column(name="EMP_ID")
private Integer employeeId;

其次,这不是你应该如何实现EmployeeId 复合键类。见:https://stackoverflow.com/a/3588400/1981720

第三,异常是数据库抛出的,不是Hibernate。检查您是否在另一个数据库中遇到相同的异常。

【讨论】:

    猜你喜欢
    • 2016-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-16
    • 1970-01-01
    • 2019-08-18
    相关资源
    最近更新 更多