Rom*_*ain 5 java orm inheritance annotations hibernate
我使用Hibernate来持久化继承的对象,但是当我尝试在数据库中持久保存对象时,我得到了这条消息:
org.springframework.dao.InvalidDataAccessResourceUsageException: Could not execute
JDBC batch update; SQL [update Widget set CONTAINER_ID=? where WIDGET_ID=?]; nested
exception is org.hibernate.exception.SQLGrammarException:
Could not execute JDBC batch update (...) Caused by: java.sql.BatchUpdateException: Table
'schema.widget' doesn't exist
Run Code Online (Sandbox Code Playgroud)
这是我用来生成表的类:
@Entity
@Table(name="CONTAINER")
public class Container {
(...)
private Set<Widget> widgets;
@OneToMany(targetEntity = Widget.class)
@JoinColumn(name="CONTAINER_ID", nullable=true)
public Set<Widget> getWidgets() {
return widgets;
}
public void setWidgets(Set<Widget> widgets) {
this.widgets = widgets;
}
}
@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public abstract class Widget {
private long id;
private int position;
@Id
@GeneratedValue(strategy = GenerationType.TABLE)
@Column(name="WIDGET_ID")
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
@Column(name="POSITION")
public int getPosition() {
return position;
}
public void setPosition(int position) {
this.position = position;
}
}
@Entity
@Table(name="TEXT_WIDGET")
public class TextWidget extends Widget {
(...)
}
@Entity
@Table(name="IMAGE_WIDGET")
public class ImageWidget extends Widget {
(...)
}
Run Code Online (Sandbox Code Playgroud)
所以这意味着Hibernate正在寻找表'widget',但它没有被创建,因为我选择了InheritanceType.TABLE_PER_CLASS选项,因此只有具体的类有一个表.在数据库中,我可以看到container,text_widget和image_widget表.
然后当我尝试执行此代码并保存容器时,我得到了上述错误:
Set<Widget> widgets = new HashSet<Widget>();
widgets.add(textw1); // instance of TextWidget
widgets.add(imgw1); // instance of ImageWidget
Container container1 = new Container();
container1.setWidgets(widgets);
Run Code Online (Sandbox Code Playgroud)
谢谢你的帮助!
您的关联必须是双向的,如Hibernate文档中所述.
2.2.4.1.每班表
这个策略有很多缺点(尤其是多态查询和关联),在JPA规范,Hibernate参考文档,Hibernate in Action以及许多其他地方都有解释.Hibernate解决了大多数使用SQL UNION查询实现此策略的问题.它通常用于继承层次结构的顶级:
Run Code Online (Sandbox Code Playgroud)@Entity @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) public class Flight implements Serializable { ... }该策略支持一对多关联,前提是它们是双向的.此策略不支持IDENTITY生成器策略:必须在多个表之间共享id.因此,在使用此策略时,不应使用AUTO或IDENTITY.
这样,Hibernate就能够在每个具体的widget表中创建适当的外键列.这是一个实际有效的映射.对于Container:
@Entity
public class Container {
@Id @GeneratedValue
private long id;
@OneToMany(targetEntity = Widget.class, mappedBy = "container", cascade = CascadeType.ALL)
private Set<Widget> widgets = new HashSet<Widget>();
public long getId() { return id; }
public void setId(long id) { this.id = id; }
public Set<Widget> getWidgets() { return widgets; }
public void setWidgets(Set<Widget> widgets) { this.widgets = widgets; }
public void addToWidgets(Widget widget) {
this.getWidgets().add(widget);
widget.setContainer(this);
}
public void removeFromWidgets(Widget widget) {
this.getWidgets().remove(widget);
widget.setContainer(null);
}
}
Run Code Online (Sandbox Code Playgroud)
而抽象的Widget类:
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Widget {
@Id @GeneratedValue(strategy = GenerationType.TABLE)
private long id;
private int position;
@ManyToOne
private Container container;
public long getId() { return id; }
public void setId(long id) { this.id = id; }
public int getPosition() { return position; }
public void setPosition(int position) { this.position = position; }
public Container getContainer() { return container; }
public void setContainer(Container container) { this.container = container; }
}
Run Code Online (Sandbox Code Playgroud)
以下测试方法(在事务中运行)只是传递:
@Test
public void testInsertContainer() {
TextWidget textw1 = new TextWidget();
ImageWidget imgw1 = new ImageWidget();
Container container1 = new Container();
container1.addToWidgets(textw1); // instance of TextWidget
container1.addToWidgets(imgw1); // instance of ImageWidget
session.persist(container1);
session.flush();
assertNotNull(textw1.getId());
assertNotNull(imgw1.getId());
assertNotNull(container1.getId());
}
Run Code Online (Sandbox Code Playgroud)
并生成以下SQL:
21:59:57.964 [main] DEBUG org.hibernate.SQL - select next_hi from hibernate_unique_key for read only with rs 21:59:57.978 [main] DEBUG org.hibernate.SQL - update hibernate_unique_key set next_hi = ? where next_hi = ? 21:59:58.063 [main] DEBUG org.hibernate.SQL - null 21:59:58.125 [main] DEBUG org.hibernate.SQL - insert into Container (id) values (?) Hibernate: insert into Container (id) values (?) 21:59:58.140 [main] TRACE org.hibernate.type.LongType - binding '98304' to parameter: 1 21:59:58.145 [main] DEBUG org.hibernate.SQL - insert into ImageWidget (container_id, position, id) values (?, ?, ?) Hibernate: insert into ImageWidget (container_id, position, id) values (?, ?, ?) 21:59:58.164 [main] TRACE org.hibernate.type.LongType - binding '98304' to parameter: 1 21:59:58.165 [main] TRACE org.hibernate.type.IntegerType - binding '0' to parameter: 2 21:59:58.166 [main] TRACE org.hibernate.type.LongType - binding '32768' to parameter: 3 21:59:58.172 [main] DEBUG org.hibernate.SQL - insert into TextWidget (container_id, position, id) values (?, ?, ?) Hibernate: insert into TextWidget (container_id, position, id) values (?, ?, ?) 21:59:58.187 [main] TRACE org.hibernate.type.LongType - binding '98304' to parameter: 1 21:59:58.188 [main] TRACE org.hibernate.type.IntegerType - binding '0' to parameter: 2 21:59:58.189 [main] TRACE org.hibernate.type.LongType - binding '32769' to parameter: 3
但请记住,每个类策略的表对多态关系提供的支持很少,如果你有很多Widget孩子,可能根本不适合(这将导致巨大的SQL UNION).
| 归档时间: |
|
| 查看次数: |
11414 次 |
| 最近记录: |