JPA @ElementCollection 生成奇怪的唯一键

JPA @ElementCollection generates strange unique key

我有一个实体 class PositionOrdering,其中包含一个元素集合:

@ElementCollection(targetClass = Position.class, fetch = FetchType.EAGER)
@CollectionTable(name = "POSITION_ORDERING_POSITION", 
     joinColumns = @JoinColumn(name = "position_ordering_id"))
@OrderColumn
List<Position> positions = new ArrayList<>();    

当hibernate生成数据库结构时,它看起来是这样的:

CREATE TABLE wls.position_ordering_position
(
    position_ordering_id bigint NOT NULL,
    positions_id bigint NOT NULL,
    positions_order integer NOT NULL,
    ...
}

没关系,完全符合我的预期。 但它还在 positions_id 列上生成一个唯一的约束。 这很奇怪,因为位置 ID 应该只在每次排序时是唯一的,所以以下任何唯一键都可以:

但不在positions_id的单列上。

因为约束是自动生成的,我不能简单地忽略或删除它。

我能否配置我的集合以创建正确的唯一约束或至少不创建任何约束?

更新:

至于请求,这里是 Position 实体的骨架:

@Entity
@SequenceGenerator(name = EntityBase.SEQUENCE_NAME, 
       sequenceName = "POSITION_ID_SEQ")
@Table(name = "position")
public class Position extends EntityBase {

    // Lots of fields, like row, column number, and type, etc.
}

其中 EntityBase 是一个简单的 class,具有一些实用函数和 Id:

@MappedSuperclass
public abstract class EntityBase implements Serializable, Cloneable {

    public static final String SEQUENCE_NAME = "SEQUENCE_GENERATOR";

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO, generator = SEQUENCE_NAME)
    protected Long id;

     //..
}

@ElementCollection用于映射基本类型或@Embedded类,不是实体。来自 the documentation

An ElementCollection can be used to define a one-to-many relationship to an Embeddable object, or a Basic value (such as a collection of Strings).

由于 Position@Entity,您应该将其映射为 @OneToMany@ManyToMany。我不知道您生成唯一密钥的确切原因,但我想如果您在 a was 中使用注释,则可能会出现不可预测的结果。

正如 Predrag Maric 在接受的答案中所描述的那样,问题在于 Position 不是“可嵌入的”。我的解决方案是:

我创建了一个支持 class,它将 Position 包装到一个 @Embeddable 实体中:

@Embeddable
//@Table(name = "position_ordering_position")
public class PositionOrderingPosition {

   @ManyToOne(fetch = FetchType.EAGER)
   @JoinColumn(name = "position_id", nullable = false)
   private Position position;

   public PositionOrderingPosition() {
   }

   public PositionOrderingPosition(Position position) {
       this.position = position;
   }

    public Position getPosition() {
        return position;
    }
}

此外,我将元素集合更改为:

@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(name = "POSITION_ORDERING_POSITION", 
    joinColumns = @JoinColumn(name = "position_ordering_id"))
@OrderColumn
List<PositionOrderingPosition> positions = new ArrayList<>();

现在它创建相同的 table,但具有正确的约束。