JPA @ElementCollection生成奇怪的唯一键

时间:2015-01-23 11:00:19

标签: sql hibernate jpa

我有一个实体类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列上生成一个独特的contsraint。这很奇怪,因为位置ID应该只对每个订单唯一,所以以下任何一个唯一键都可以:

  • position_ordering_id + positions_order
  • position_ordering_id + positions_id

但不是在position_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是一个带有一些效用函数且带有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;

     //..
}

2 个答案:

答案 0 :(得分:2)

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

  

ElementCollection 可用于定义与Embeddable对象的一对多关系,或Basic值(例如字符串集合)。

由于Position@Entity,您应将其映射为@OneToMany@ManyToMany。我不知道你为什么要生成这个唯一密钥的确切原因,但我想如果你在a中使用annottion,那么你可能会得到不可预知的结果。

答案 1 :(得分:0)

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

我创建了一个支持类,它将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;
    }
}

我还将Element集合更改为:

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

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