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了。








發佈了53 篇原創文章 · 獲贊 2 · 訪問量 48萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章