java Hibernate注解多对一映射生成奇数模式
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4083744/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Hibernate annotation many-to-one mapping generating odd schema
提问by speshak
I have a fairly simple Many to One relationship between two classes:
我在两个类之间有一个相当简单的多对一关系:
@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 generates the following tables (in Postgres)
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) |
The step table is what I expect, but I don't understand why the steps(bytea) column is there. Am I doing something wrong in my mapping or do I just not understand how hibernate works?
步骤表是我所期望的,但我不明白为什么 step(bytea) 列在那里。我在映射中做错了什么,或者我只是不明白休眠是如何工作的?
回答by Pascal Thivent
I suspect the problem is that you're using a concrete HashSet
instead of the Set
interface. Try this (assuming it has an Id
somewhere):
我怀疑问题在于您使用的是具体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
}
Also note how I initialized the steps property. Let me quote the documentation about this:
还要注意我是如何初始化 steps 属性的。让我引用有关此的文档:
6.1. Persistent collections
...
Notice how the instance variable was initialized with an instance of HashSet. This is the best way to initialize collection valued properties of newly instantiated (non-persistent) instances. When you make the instance persistent, by calling persist() for example, Hibernate will actually replace the HashSet with an instance of Hibernate's own implementation of Set.
6.1. 持久化集合
...
注意实例变量是如何用 HashSet 的实例初始化的。这是初始化新实例化(非持久)实例的集合值属性的最佳方式。当您使实例持久化时,例如通过调用 persist(),Hibernate 实际上会用 Hibernate 自己的 Set 实现的实例替换 HashSet。
And make sure that:
并确保:
- both entities have an
@Id
property (the part you're showing is not enough to confirm that). Step
is implementingequals
/hashCode
correctly (see the references below).
- 两个实体都有一个
@Id
属性(您显示的部分不足以确认这一点)。 Step
正在实施equals
/hashCode
正确(请参阅下面的参考资料)。
References
参考
- Hibernate Core Reference Guide
- Hibernate 核心参考指南
Update:Can't reproduce (I don't have PostgreSQL installed by I don't thinkit is that relevant). I used the following entities:
更新:无法重现(我没有安装 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
}
And:
和:
@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
}
Here is the generated DDL:
这是生成的 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
I don't even understand how you could use a HashSet
in your OneToMany
, Hibernate complained (as expected to be honest) when I tried:
我什至不明白您如何HashSet
在您的OneToMany
.hibernate 中使用 a ,当我尝试时,Hibernate 抱怨(老实说):
Caused by: org.hibernate.AnnotationException: Illegal attempt to map a non collection as a @OneToMany, @ManyToMany or @CollectionOfElements: com.stackoverflow.q4083744.Schedule.steps