gpt4 book ai didi

java - hibernate 和继承(TABLE_PER_CLASS)

转载 作者:搜寻专家 更新时间:2023-10-31 19:50:28 26 4
gpt4 key购买 nike

我使用 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

这是我用来生成表格的类:

@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 {
(...)
}

所以这意味着 Hibernate 正在寻找表“小部件”,但它没有创建,这是有道理的,因为我选择了 InheritanceType.TABLE_PER_CLASS 选项,然后只有具体类才有表。在数据库中,我可以看到容器、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);

感谢您的帮助!

最佳答案

您的关联必须是双向的,如 Hibernate 文档中所述。

2.2.4.1. Table per class

This strategy has many drawbacks (esp. with polymorphic queries and associations) explained in the JPA spec, the Hibernate reference documentation, Hibernate in Action, and many other places. Hibernate work around most of them implementing this strategy using SQL UNION queries. It is commonly used for the top level of an inheritance hierarchy:

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Flight implements Serializable { ... }

This strategy supports one-to-many associations provided that they are bidirectional. This strategy does not support the IDENTITY generator strategy: the id has to be shared across several tables. Consequently, when using this strategy, you should not use AUTO nor IDENTITY.

这样,Hibernate 将能够在每个具体的小部件表中创建适当的外键列。这是一个实际有效的映射。对于 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);
}
}

以及抽象的 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; }
}

下面的测试方法(在事务中运行)刚刚通过:

@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());
}

并生成如下SQL:

21:59:57.964 [main] DEBUG org.hibernate.SQL - select next_hi from hibernate_unique_key for read only with rs21: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 - null21: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: 121: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: 121:59:58.165 [main] TRACE org.hibernate.type.IntegerType - binding '0' to parameter: 221:59:58.166 [main] TRACE org.hibernate.type.LongType - binding '32768' to parameter: 321: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: 121:59:58.188 [main] TRACE org.hibernate.type.IntegerType - binding '0' to parameter: 221:59:58.189 [main] TRACE org.hibernate.type.LongType - binding '32769' to parameter: 3

但请记住,每个类一个表策略提供的对多态关系的支持很差,如果您有很多 Widget 可能根本不合适子(这将导致巨大的 SQL UNION)。

相关问题

关于java - hibernate 和继承(TABLE_PER_CLASS),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3557879/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com