Hibernate注释多对一映射生成奇数模式

时间:2010-11-03 02:17:19

标签: java hibernate orm jpa

我在两个类之间有一个相当简单的多对一关系:

@Entity
public class Schedule
 implements java.io.Serializable {

    private String scheduleName;
    private HashSet<Step> steps;

    @OneToMany(mappedBy="schedule", cascade=CascadeType.ALL, 
        fetch=FetchType.EAGER)
    public HashSet<Step> getSteps() {
       return steps;
    }
}

@Entity
public class Step implements java.io.Serializable {
   private Long id; 
   private String duration;
   private String stepType;
   private Schedule schedule;

   @ManyToOne(fetch=FetchType.LAZY)
   public Schedule getSchedule() {
     return schedule;
   }

   @Id
   @GeneratedValue
   public Long getId() {
       return id;
   }

}

Hibernate生成以下表格(在Postgres中)

              Table "public.schedule"
    Column    |          Type          | Modifiers 
--------------+------------------------+-----------
 uuid         | character varying(255) | not null
 version      | integer                | 
 schedulename | character varying(255) | 
 steps        | bytea                  | 


                Table "public.step"
    Column     |          Type          | Modifiers 
---------------+------------------------+-----------
 id            | bigint                 | not null
 duration      | character varying(255) | 
 steptype      | character varying(255) | 
 temperature   | numeric(19,2)          | 
 schedule_uuid | character varying(255) | 

步骤表是我所期望的,但我不明白为什么步骤(bytea)列在那里。我在映射中做错了什么,或者我不明白hibernate是如何工作的?

1 个答案:

答案 0 :(得分:6)

我怀疑问题是您使用的是具体的HashSet而不是Set界面。试试这个(假设某个地方有一个Id):

@Entity
public class Schedule implements java.io.Serializable {

    private String scheduleName;
    private Set<Step> steps = new HashSet<Step>();

    @OneToMany(mappedBy="schedule", cascade=CascadeType.ALL, fetch=FetchType.EAGER)
    public Set<Step> getSteps() {
       return steps;
    }

    // other properties, getters, setters
}

还要注意我是如何初始化steps属性的。让我引用有关此内容的文档:

  

6.1. Persistent collections

     

...

     

注意实例变量是怎样的   用一个实例初始化   HashSet的。这是最好的方法   初始化集合值   新实例化的属性   (非持久性)实例。当你   使实例持久化   以persist()为例,   Hibernate实际上会取代   带有实例的HashSet   Hibernate自己实现的Set。

并确保:

  • 两个实体都有@Id属性(您展示的部分不足以确认)。
  • Step正在正确实施equals / hashCode(请参阅下面的参考资料)。

参考


更新:无法重现(我没有安装PostgreSQL,我不认为它是相关的)。我使用了以下实体:

@Entity
public class Step implements java.io.Serializable {
    private Long id;
    private String duration;
    private String stepType;
    private Schedule schedule;

    @ManyToOne(fetch = FetchType.LAZY)
    public Schedule getSchedule() { return schedule; }

    @Id @GeneratedValue
    public Long getId() { return id; }

    // getters, setters, equals, hashCode
}

@Entity
public class Schedule implements java.io.Serializable {
    private Long id;
    private String scheduleName;
    private Set<Step> steps = new HashSet<Step>();

    @OneToMany(mappedBy = "schedule", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    public Set<Step> getSteps() { return steps; }

    @Id @GeneratedValue
    public Long getId() { return id; }

    // getters, setters
}

这是生成的DDL:

create table Schedule (
    id bigint generated by default as identity (start with 1),
    scheduleName varchar(255),
    primary key (id)
)

create table Step (
    id bigint generated by default as identity (start with 1),
    duration varchar(255),
    stepType varchar(255),
    schedule_id bigint,
    primary key (id)
)

alter table Step 
    add constraint FK277AEC7B775928 
    foreign key (schedule_id) 
    references Schedule

我甚至不明白你在HashSet中如何使用OneToMany,Hibernate在我尝试时抱怨(正如预期的那样诚实):

Caused by: org.hibernate.AnnotationException: Illegal attempt to map a non collection as a @OneToMany, @ManyToMany or @CollectionOfElements: com.stackoverflow.q4083744.Schedule.steps