这是我在学习使用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了。