Hibernate - 当在另一个类中 fk 自引用时处理添加(插入)
我的 Hibernate 配置如下。
CPUModel:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="org.example.CPUModel" table="cpu_model">
<id name="cpuModelId" type="java.lang.Integer" unsaved-value="null">
<column name="cpu_model_id"/>
<generator class="identity"/>
</id>
<property name="name" type="java.lang.String">
<column length="32" name="name"/>
</property>
<set name="softwares" inverse="true" lazy="false" table="cpu_model_software" cascade="all-delete-orphan" order-by="cpu_sw_id desc">
<key>
<column name="cpu_model_id" not-null="true"/>
</key>
<one-to-many class="org.example.CPUModelSoftware"/>
</set>
</class>
</hibernate-mapping>
CPUModelSoftware
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="org.example.CPUModelSoftware" table="cpu_model_software">
<composite-id name="cpuModelSoftwarePK" class="org.example.CPUModelSoftwarePK">
<key-property name="cpuModelId" column="cpu_model_id" type="java.lang.Integer"/>
<key-property name="cpuSwId" column="cpu_sw_id" type="java.lang.Integer"/>
</composite-id>
<many-to-one class="org.example.CPUSoftware" insert="false" update="false" fetch="select" name="cpuSw">
<column name="cpu_sw_id" not-null="true"/>
</many-to-one>
</class>
</hibernate-mapping>
选择值并更新可以正常使用此配置,但插入全新的值却行不通。
我收到此错误:
DEBUG Could not execute JDBC batch update [insert into exampledb.cpu_model_software (cpu_model_id, cpu_sw_id) values (?, ?)]
java.sql.BatchUpdateException: Column 'cpu_model_id' cannot be null
所以 Hibernate 试图在不首先从数据库生成 cpu_model_id 的情况下进行插入,然后将其设置为 CPUModelSoftwarePK (请参阅 CPUModel Hibernate 配置)
那么我如何告诉 Hibernate 它应该首先向 cpu_model 表进行插入。然后从那里获取 id 并设置 CPUModelSoftwarePK 的 id 并进行插入?
CPUModelSoftware/PK 的数据库如下。
+----------------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+---------+------+-----+---------+-------+
| cpu_model_id | int(11) | NO | MUL | NULL | |
| cpu_sw_id | int(11) | NO | MUL | NULL | |
+----------------+---------+------+-----+---------+-------+
对于 CPUModel
+----------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------+------------------+------+-----+---------+----------------+
| cpu_model_id | int(11) unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(32) | NO | | | |
+----------------+------------------+------+-----+---------+----------------+
编辑
似乎我在制作新的 CPUModelSoftware 时没有将 CPUModelSoftwarePK 设为 null。但是现在我得到了这个:
ids for this class must be manually assigned before calling save(): org.example.CPUModelSoftware
I have Hibernate configs as follows.
CPUModel:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="org.example.CPUModel" table="cpu_model">
<id name="cpuModelId" type="java.lang.Integer" unsaved-value="null">
<column name="cpu_model_id"/>
<generator class="identity"/>
</id>
<property name="name" type="java.lang.String">
<column length="32" name="name"/>
</property>
<set name="softwares" inverse="true" lazy="false" table="cpu_model_software" cascade="all-delete-orphan" order-by="cpu_sw_id desc">
<key>
<column name="cpu_model_id" not-null="true"/>
</key>
<one-to-many class="org.example.CPUModelSoftware"/>
</set>
</class>
</hibernate-mapping>
CPUModelSoftware
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="org.example.CPUModelSoftware" table="cpu_model_software">
<composite-id name="cpuModelSoftwarePK" class="org.example.CPUModelSoftwarePK">
<key-property name="cpuModelId" column="cpu_model_id" type="java.lang.Integer"/>
<key-property name="cpuSwId" column="cpu_sw_id" type="java.lang.Integer"/>
</composite-id>
<many-to-one class="org.example.CPUSoftware" insert="false" update="false" fetch="select" name="cpuSw">
<column name="cpu_sw_id" not-null="true"/>
</many-to-one>
</class>
</hibernate-mapping>
Selecting values and updating works fine with this config, but inserting a completely new value just doesn't.
I get this error:
DEBUG Could not execute JDBC batch update [insert into exampledb.cpu_model_software (cpu_model_id, cpu_sw_id) values (?, ?)]
java.sql.BatchUpdateException: Column 'cpu_model_id' cannot be null
So Hibernate is trying to make an insert without first getting generated cpu_model_id from the DB, and setting then it for CPUModelSoftwarePK (see CPUModel Hibernate config)
So how do I tell Hibernate that it should first make an insert to cpu_model table. Then get the id from there and set the id for CPUModelSoftwarePK and make insert?
The db for CPUModelSoftware/PK is as follows.
+----------------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+---------+------+-----+---------+-------+
| cpu_model_id | int(11) | NO | MUL | NULL | |
| cpu_sw_id | int(11) | NO | MUL | NULL | |
+----------------+---------+------+-----+---------+-------+
and for CPUModel
+----------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------+------------------+------+-----+---------+----------------+
| cpu_model_id | int(11) unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(32) | NO | | | |
+----------------+------------------+------+-----+---------+----------------+
EDIT
It seems that I wasn't nulling CPUModelSoftwarePK when making a new CPUModelSoftware. However now I am getting this:
ids for this class must be manually assigned before calling save(): org.example.CPUModelSoftware
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
据我了解,Hibernate 不支持
hbm.xml
中定义的映射中的派生标识。这意味着 Hibernate 无法根据CPUModel
和CPUModelSoftware
之间的关系自动设置cpuModelId
的值。因此,您需要先保存
CPUModel
(带有空软件
),然后需要将其生成的标识符分配给CPUModelSoftware
的字段compisite id,并保存CPUModelSoftware
。As far as I understand, Hibernate doesn't support derived identities in mappings defined in
hbm.xml
. It means that Hibernate can't set value ofcpuModelId
automatically based on relationship betweenCPUModel
andCPUModelSoftware
.Thus, you need to save
CPUModel
(with emptysoftwares
) first, then you need to assign its generated identifier to the field ofCPUModelSoftware
's compisite id, and saveCPUModelSoftware
.