**
hibernate 单向多对一 参照非主键 插入数据库
当插入数据库记录时,报出外键约束的问题。
表结构如下
其中两张表中id都为业务逻辑无关主键,major表中的 institute_id参照 Institute表中的institute_id, 而Institute表中的institute_id并非主键。
如果你子表参照主表的字段是主键时,就可能不会有一下的错误
-- -----------------------------------------------------
-- Table Institute
-- -----------------------------------------------------
DROP TABLE Institute ;
CREATE TABLE Institute(
id INT NOT NULL IDENTITY,
institute_id VARCHAR(20) NOT NULL UNIQUE,
institute_name VARCHAR(45) NOT NULL UNIQUE,
bean VARCHAR(20) NOT NULL,
major_amount INT NOT NULL,
PRIMARY KEY (id))
-- -----------------------------------------------------
-- Table Major
-- -----------------------------------------------------
DROP TABLE Major ;
CREATE TABLE Major (
id INT NOT NULL IDENTITY,
major_id VARCHAR(20) NOT NULL UNIQUE,
major_name VARCHAR(45) NOT NULL,
institute_id VARCHAR(20),
PRIMARY KEY (id),
CONSTRAINT fk_tb_major_tb_institute1
FOREIGN KEY (institute_id)
REFERENCES SMS_Institute (institute_id)
ON DELETE CASCADE
ON UPDATE CASCADE)
通过hibernate方向生成的实体类
关联为多对一,major表管理institute表
Institute.class
package com.domain;
import java.util.HashSet;
import java.util.Set;
/**
* Institute entity. @author MyEclipse Persistence Tools
*/
public class SmsInstitute implements java.io.Serializable {
// Fields
private Integer id;
private String instituteId;
private String instituteName;
private String bean;
private Integer majorAmount;
//getter和setter方法省略
}
institute.hbm.xml文件
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<class name="com.domain.Institute" table="SMS_Institute" >
<!--业务逻辑无关主键 ,自增-->
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="identity"></generator>
</id>
<!--学院ID -->
<property name="instituteId" type="java.lang.String">
<column name="institute_id" length="20" not-null="true" unique="true" />
</property>
<!--学院名称-->
<property name="instituteName" type="java.lang.String">
<column name="institute_name" length="45" not-null="true" unique="true" />
</property>
<!--院长-->
<property name="bean" type="java.lang.String">
<column name="bean" length="20" not-null="true" />
</property>
<!--专业数量-->
<property name="majorAmount" type="java.lang.Integer">
<column name="major_amount" not-null="true" />
</property>
</class>
</hibernate-mapping>
Major.class
package com.domain;
/**
* SmsMajor entity. @author MyEclipse Persistence Tools
*/
public class SmsMajor implements java.io.Serializable {
// Fields
private Integer id;
private String majorId;
private String majorName;
private SmsInstitute institute;
//getter和setter方法省略
}
major.hbm.xml文件
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- Mapping file autogenerated by MyEclipse Persistence Tools -->
<hibernate-mapping>
<class name="com.domain.SmsMajor" table="Major" >
<!--业务逻辑无关主键 ,自增-->
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="identity"></generator>
</id>
<!--专业ID-->
<property name="majorId" type="java.lang.String">
<column name="major_id" length="20" not-null="true" unique="true" />
</property>
<!--专业姓名-->
<property name="majorName" type="java.lang.String">
<column name="major_name" length="45" not-null="true" />
</property>
<!--单向多对一映射-->
<many-to-one name="institute" class="com.domain.SmsInstitute" property-ref="instituteId">
<column name="institute_id" ></column>
</many-to-one>
</class>
</hibernate-mapping>
其中many-to-one中的属性property-ref="instituteId"起到重要作用,把外键参考的值指向institute表中的institute_id字段。(ps:可能不设置property-ref属性的话,hibernate会把外键参考的值指向institute表中的主键,也就是我设置的业务逻辑无关主键,从而曝出外键约束错误。可能可能可能,重要的事情说三遍,我也不太确定)
往数据库中插入新纪录
public int insertMajor(String majorId, String majorName, String instituteId) {
// TODO Auto-generated method stub
try{
Session sess=HibernateUtils.getSession();//获取session
sess.beginTransaction();//开启事务
InstituteDAOImpl sidi= newInstituteDAOImpl();
Institute si= sidi.selectByInstituteId(instituteId);//获取所参照学院的对象
//实例化专业对象
Major major= new Major();
major.setMajorId(majorId);
major.setMajorName(majorName);
major.setInstitute(si);//设置major属性
sess.save(major);//将专业对象保存到数据库
sess.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
return 0;//返回值判断是否插入成功
}
return 1;
如过many-to-one中没有设置属性property-ref的值,会报外键约束错误,错误提示如下
org.hibernate.util.JDBCExceptionReporter logExceptions
严重: INSERT 语句与 FOREIGN KEY 约束"fk_tb_major_tb_institute1"冲突。该冲突发生于数据库"SMS",表"Institute", column ‘institute_id’。
org.hibernate.exception.ConstraintViolationException: could not insert: [com.domain.Major]
设置好many-to-one中的属性property-ref的值,就不会报错。