hibernate 具有主外键关系的多表级联保存

这是我在学习使用hibernate进行多表级联保存时,遇到的问题,记录下来以便日后查找。


微博图片表

SayFiles.hbm.xml

<?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">
<!-- 
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
    <class name="com.gifer.model.SayFiles" table="SAY_FILES" schema="GIFER">
        <id name="fileId" type="java.lang.Long">
            <column name="FILE_ID" precision="18" scale="0" />
            <generator class="sequence">
            	<param name="sequence">SEQ_SAY_FILES</param>
            </generator>
        </id>
        <many-to-one name="sayMessage" class="com.gifer.model.SayMessage" fetch="select">
            <column name="SAY_ID" precision="18" scale="0" />
        </many-to-one>
        <property name="fileName" type="java.lang.String">
            <column name="FILE_NAME" length="200" />
        </property>
        <property name="fileUrl" type="java.lang.String">
            <column name="FILE_URL" length="200" />
        </property>
        <property name="uploadTime" type="java.sql.Timestamp">
            <column name="UPLOAD_TIME" length="7" />
        </property>
    </class>
</hibernate-mapping>


微博主表

SayMessage.hbm.xml

<?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">
<!-- 
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
    <class name="com.gifer.model.SayMessage" table="SAY_MESSAGE" schema="GIFER">
        <id name="sayId" type="java.lang.Long">
            <column name="SAY_ID" precision="18" scale="0" />
            <generator class="sequence">
            	<param name="sequence">SEQ_SAY_MESSAGE</param>
            </generator>
        </id>
        <property name="sayContent" type="java.lang.String">
            <column name="SAY_CONTENT" length="280" not-null="true" />
        </property>
        <property name="sayTime" type="java.sql.Timestamp">
            <column name="SAY_TIME" length="7" not-null="true" />
        </property>
        <property name="sayUser" type="java.lang.String">
            <column name="SAY_USER" length="50" not-null="true" />
        </property>
        <set name="sayFileses" inverse="true"  cascade="save-update" >
            <key>
                <column name="SAY_ID" precision="18" scale="0" />
            </key>
            <one-to-many class="com.gifer.model.SayFiles" />
        </set>
        <set name="replyMessages" inverse="true">
            <key>
                <column name="SAY_ID" precision="18" scale="0" />
            </key>
            <one-to-many class="com.gifer.model.ReplyMessage" />
        </set>
    </class>
</hibernate-mapping>

微博图片表SayFiles的SAY_ID属性依赖于微博主表SayMessage的主键SAY_ID

action处理代码

			// 组织成微博实体对象
			SayMessage sayMessage = new SayMessage();
			sayMessage.setSayContent(this.getSayMessage());
			Timestamp sayTime = new Timestamp(System.currentTimeMillis());
			sayMessage.setSayTime(sayTime);// 当前时间
			LoginUser sayUser = (LoginUser) ActionContext.getContext()
					.getSession().get("user");// 从session中获取用户信息
			sayMessage.setSayUser(sayUser.getUserId());

			Set sayFiles = new HashSet();

			// 把得到的文件的集合通过循环的方式读取并放在指定的路径下
			for (int i = 0; i < upload.size(); i++) {
				try {
					SayFiles sayFile = new SayFiles();

					String oldFileName = uploadFileName.get(i);// 上传文件原名

					// 生成随机文件名:当前年月日时分秒+五位随机数(为了在实际项目中防止文件同名而进行的处理)
					Random r = new Random();
					int rannum = (int) (r.nextDouble() * (99999 - 10000 + 1)) + 10000; // 获取随机数
					SimpleDateFormat sDateFormat = new SimpleDateFormat(
							"yyyyMMddHHmmss"); // 时间格式
					String nowTimeStr = sDateFormat.format(new Date()); // 当前时间字符串
					String extName = "";
					// 获取拓展名
					if (oldFileName.lastIndexOf(".") >= 0) {
						extName = oldFileName.substring(oldFileName
								.lastIndexOf("."));
					}
					// 新文件名
					String newFileName = nowTimeStr + rannum + extName;
					relativeUrl += newFileName;// 文件保存到数据库中的相对路径
					// list集合通过get(i)的方式来获取索引
					// 将文件逐一复制到指定目录
					FileUtils.copyFile(upload.get(i), new File(files,
							newFileName));
					sayFile.setFileName(oldFileName);
					sayFile.setFileUrl(relativeUrl);
					sayFile.setUploadTime(sayTime);
					sayFile.setSayMessage(sayMessage);
					sayFiles.add(sayFile);
				} catch (IOException e) {
					log.error(e.getMessage(), e);
				}
			}
			sayMessage.setSayFileses(sayFiles);
			this.sayMessageService.save(sayMessage);//调用主键的保存方法

利用主表来保存,刚开始没有加cascade="save-update",结果,微博主表记录插入成功,微博图片表记录没有插入。

<set name="sayFileses" inverse="true" >
            <key>
                <column name="SAY_ID" precision="18" scale="0" />
            </key>
            <one-to-many class="com.gifer.model.SayFiles" />
        </set>
加上属性:cascade="save-update"后,结果,微博主表记录插入成功,微博图片表记录插入也成功了,但是外键SAY_ID是null。

<set name="sayFileses" inverse="true"  cascade="save-update" >
            <key>
                <column name="SAY_ID" precision="18" scale="0" />
            </key>
            <one-to-many class="com.gifer.model.SayFiles" />
</set>

原因是在给微博图片表实体,设置属性时,漏掉了下面这句,没有给其设置外键值的引用对象

sayFile.setSayMessage(sayMessage);

加上后,两个表的插入操作都OK了。








展开阅读全文

没有更多推荐了,返回首页