Code Bye

设计多张1对多表的hibernate一对多级联删除

大体是这样子的思路:Forum 1:n Course        Course 1:nTopic               Topic 1:n Reply
总共四张表,想要问下:多张有联系的一对多的表,hibernate设置级联删除是否跟  一张的一对多的级联删除有不一样的地方???

一张的,我成功过。所以我想引入两张的,然后JUnit 测试数据竟然过不了。

2014-12-23 18:31:03,550 ERROR [org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:324)] – Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener@2dd4708d] to prepare test instance [cn.edu.fjnu.java1.cdio2.yplan.service.ForumServiceTest@5629507c]
 java.lang.IllegalStateException: Failed to load ApplicationContext


40分
容器貌似都没加载成功,实体配置有问题吧?贴出代码看看
/**
 * 
 */
package cn.edu.fjnu.java1.cdio2.yplan.domain;

import java.util.Set;

/**
 * 类的作用:论坛年级版块的实体类
 * 
 * @author chenjie
 * @version 1.0
 * @创建时间 2014年12月17日  下午5:50:32
 */
public class Forum {

	/**实体Forum的主键*/
	private Long forumID;

	/**版块的名称*/
	private String forumName;

	/**版块的描述*/
	private String forumDescription;

	/**版块排序位置号*/
	private int forumPosition;

	/**版块前置图片*/
	private String mouseOutIconPath;

	/**版块后置图片*/
	private String mouseOnIconPath;


	private Set<Course> courses;



	/**
	 * 
	 */
	public Forum() {
		super();
		// TODO Auto-generated constructor stub
	}



	/**
	 * @param forumID
	 */
	public Forum(Long forumID) {
		super();
		this.forumID = forumID;
	}



	/**
	 * @param forumName
	 * @param forumDescription
	 * @param forumPosition
	 * @param mouseOutIconPath
	 * @param mouseOnIconPath
	 */
	public Forum(String forumName, String forumDescription, int forumPosition,
			String mouseOutIconPath, String mouseOnIconPath) {
		super();
		this.forumName = forumName;
		this.forumDescription = forumDescription;
		this.forumPosition = forumPosition;
		this.mouseOutIconPath = mouseOutIconPath;
		this.mouseOnIconPath = mouseOnIconPath;
	}




	/**
	 * @return the forumID
	 */
	public Long getForumID() {
		return forumID;
	}



	/**
	 * @param forumID the forumID to set
	 */
	public void setForumID(Long forumID) {
		this.forumID = forumID;
	}



	/**
	 * @return the forumName
	 */
	public String getForumName() {
		return forumName;
	}



	/**
	 * @param forumName the forumName to set
	 */
	public void setForumName(String forumName) {
		this.forumName = forumName;
	}



	/**
	 * @return the forumDescription
	 */
	public String getForumDescription() {
		return forumDescription;
	}



	/**
	 * @param forumDescription the forumDescription to set
	 */
	public void setForumDescription(String forumDescription) {
		this.forumDescription = forumDescription;
	}



	/**
	 * @return the forumPosition
	 */
	public int getForumPosition() {
		return forumPosition;
	}



	/**
	 * @param forumPosition the forumPosition to set
	 */
	public void setForumPosition(int forumPosition) {
		this.forumPosition = forumPosition;
	}



	/**
	 * @return the mouseOutIconPath
	 */
	public String getMouseOutIconPath() {
		return mouseOutIconPath;
	}



	/**
	 * @param mouseOutIconPath the mouseOutIconPath to set
	 */
	public void setMouseOutIconPath(String mouseOutIconPath) {
		this.mouseOutIconPath = mouseOutIconPath;
	}



	/**
	 * @return the mouseOnIconPath
	 */
	public String getMouseOnIconPath() {
		return mouseOnIconPath;
	}



	/**
	 * @param mouseOnIconPath the mouseOnIconPath to set
	 */
	public void setMouseOnIconPath(String mouseOnIconPath) {
		this.mouseOnIconPath = mouseOnIconPath;
	}





	/**
	 * @return the courses
	 */
	public Set<Course> getCourses() {
		return courses;
	}



	/**
	 * @param courses the courses to set
	 */
	public void setCourses(Set<Course> courses) {
		this.courses = courses;
	}



	/**
	 * 重写toString方法
	 */
	@Override
	public String toString() {

		return "Forum [forumID=" + forumID+",forumName=" + forumName +",forumDescription=" + forumDescription +
				",forumPosition=" + forumPosition + ",mouseOutIconPath=" + mouseOutIconPath +
				",mouseOnIconPath=" + mouseOnIconPath + "]";
	}
}
/**
 * 
 */
package cn.edu.fjnu.java1.cdio2.yplan.domain;

import java.util.Set;

import com.sun.org.apache.xpath.internal.FoundIndex;

/**
 * @author chenjie
 * @version 1.0
 * @创建时间 2014年12月21日  上午10:28:48
 */
public class Course {


	/**实体Course的主键*/
	private Long courseID;
	/**课程名称*/
	private String courseName;
	/**课程所属年级*/
	private Forum forum;

	private Set<Topic> topics;




	/**
	 * 
	 */
	public Course() {

	}












	/**
	 * @param courseName
	 * @param forum
	 */
	public Course(String courseName, Forum forum) {
		super();
		this.courseName = courseName;
		this.forum = forum;
	}












	/**
	 * @param courseID
	 */
	public Course(Long courseID) {
		super();
		this.courseID = courseID;
	}



	//*******************************setter和getter*****************************




	/**
	 * @return the courseID
	 */
	public Long getCourseID() {
		return courseID;
	}



	/**
	 * @param courseID the courseID to set
	 */
	public void setCourseID(Long courseID) {
		this.courseID = courseID;
	}



	/**
	 * @return the courseName
	 */
	public String getCourseName() {
		return courseName;
	}



	/**
	 * @param courseName the courseName to set
	 */
	public void setCourseName(String courseName) {
		this.courseName = courseName;
	}






	/**
	 * @return the forum
	 */
	public Forum getForum() {
		return forum;
	}



	/**
	 * @param forum the forum to set
	 */
	public void setForum(Forum forum) {
		this.forum = forum;
	}






	/**
	 * @return the topics
	 */
	public Set<Topic> getTopics() {
		return topics;
	}












	/**
	 * @param topics the topics to set
	 */
	public void setTopics(Set<Topic> topics) {
		this.topics = topics;
	}












	/**
	 * 覆写Course的toString方法
	 * 
	 */

	@Override
	public String toString() {

		return "Course [ courseID = " + courseID + ",courseName = " + courseName + ",Forum = " + forum.getForumID();
	}


}
/**
 * 
 */
package cn.edu.fjnu.java1.cdio2.yplan.domain;

import java.util.Date;
import java.util.Set;

/**
 * 继承实体类Article
 * @author chenjie
 * @version 1.0
 * @创建时间 2014年12月22日  下午2:39:02
 */
public class Topic extends Article {

	/** 普通帖 */
	//public static final int TYPE_NORMAL = 0;

	/** 精华帖 */
	//public static final int TYPE_BEST = 1;

	/** 置顶帖 */
	//public static final int TYPE_TOP = 2;

	/**帖子的类型*/
	private int topicType;

	/**帖子所属的科目*/
	private Course course;



	/**帖子下的回复*/
	//private Set<Reply> replies;
	//

	/**帖子最后的回复者*/
	//private User user;

	/**帖子最后的回复时间*/
	//private Date topicLastReplyTime;

	/**帖子回复的数量*/
	//private int topicReplyCount;


	/**
	 * 
	 */
	public Topic() {
		super();
		// TODO Auto-generated constructor stub
	}



	/**
	 * @param id
	 */
	public Topic(Long id) {
		super(id);
		// TODO Auto-generated constructor stub
	}



	/**
	 * @param topicType
	 * @param course
	 */
	public Topic(int topicType, Course course) {
		super();
		this.topicType = topicType;
		this.course = course;
	}



	/**
	 * @return the topicType
	 */
	public int getTopicType() {
		return topicType;
	}



	/**
	 * @param topicType the topicType to set
	 */
	public void setTopicType(int topicType) {
		this.topicType = topicType;
	}



	/**
	 * @return the course
	 */
	public Course getCourse() {
		return course;
	}



	/**
	 * @param course the course to set
	 */
	public void setCourse(Course course) {
		this.course = course;
	}








}

以上是3个实体,关系如1楼所说

引用 1 楼 zhangjihao 的回复:

容器貌似都没加载成功,实体配置有问题吧?贴出代码看看

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="cn.edu.fjnu.java1.cdio2.yplan.domain">
	<class name="Forum">
	   <!--  主键id -->
		<id name="forumID">
		<!-- 主键采用自增长的方式 -->
			<generator class="native" />
		</id>
		<!-- 年级版块的名称  -->
		<property name="forumName" />
		<!-- 年级版块的描述 -->
		<property name="forumDescription" />
		<!-- 年级版块的排序位置 -->
		<property name="forumPosition" />
		<!-- 动态效果前置图(暂定) -->
		<property name="mouseOnIconPath" />
		<!-- 动态效果后置图(暂定)properties的作用 -->
		<property name="mouseOutIconPath" />

		<set name="courses" cascade="delete">
		  <key column="forumID"></key>
		  
		  <one-to-many class="Course"></one-to-many>
		</set>
	</class>

</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="cn.edu.fjnu.java1.cdio2.yplan.domain">
	<class name="Course" lazy="false">
	   <!--  主键id -->
		<id name="courseID">
		<!-- 主键采用自增长的方式 -->
			<generator class="native" />
		</id>
		<!-- 课程名  -->
		<property name="courseName" />


		<!-- 所属年级版块ID -->
		<!-- forum属性,本类与Forum的多对一 ,一个版块包含多个帖子-->

		<many-to-one name="forum" class="Forum" column="forumID"></many-to-one> 

		<set name="topics" cascade="delete">
		  <key column="courseID"></key>
		  
		  <one-to-many class="Topic" ></one-to-many>
		  </set>

	</class>

</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="cn.edu.fjnu.java1.cdio2.yplan.domain">
	<class name="Topic" lazy="false">
	   <!--  主键id -->
		<id name="id">
		<!-- 主键采用自增长的方式 -->
			<generator class="native" />
		</id>
		<!-- 帖子标题 -->
		<property name="title" />
		<!-- 帖子内容 -->
		<property name="content" type="text" length="20000"/>
		<!-- 帖子发表时间 -->
		<property name="postTime" type="timestamp"/>
		<!-- 帖子作者发帖时的ip地址 -->
		<property name="ipAddr"/>

		<property name="topicType"/>


		<!-- 所属课程的课程ID -->
		<!-- course属性,本类与Course的多对一 ,一个课程下包含多个帖子-->

		<many-to-one name="course" class="Course" column="courseID"></many-to-one> 

	</class>

</hibernate-mapping>

以上三个文件是 数据库映射 xml配置文件

引用 1 楼 zhangjihao 的回复:

容器貌似都没加载成功,实体配置有问题吧?贴出代码看看

现在的一个问题是,我现在用junit测试,前面两张 forumTest 和courseTest测试都成功通过,并且在mysql建起表有数据,然后topicTest 能够建表,但是空数据。并且报错:

org.springframework.dao.InvalidDataAccessApiUsageException: object references an unsaved transient instance - save the transient instance before flushing: cn.edu.fjnu.java1.cdio2.yplan.domain.Course; nested exception is org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: cn.edu.fjnu.java1.cdio2.yplan.domain.Course
	at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:654)
	at org.springframework.orm.hibernate3.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:793)
	at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:664)
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393)
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
	at com.sun.proxy.$Proxy11.save(Unknown Source)
	at cn.edu.fjnu.java1.cdio2.yplan.service.TopicServiceTest.testSave(TopicServiceTest.java:40)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
	at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82)
	at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: cn.edu.fjnu.java1.cdio2.yplan.domain.Course
	at org.hibernate.engine.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:243)
	at org.hibernate.type.EntityType.getIdentifier(EntityType.java:456)
	at org.hibernate.type.ManyToOneType.isDirty(ManyToOneType.java:265)
	at org.hibernate.type.ManyToOneType.isDirty(ManyToOneType.java:275)
	at org.hibernate.type.TypeHelper.findDirty(TypeHelper.java:295)
	at org.hibernate.persister.entity.AbstractEntityPersister.findDirty(AbstractEntityPersister.java:3403)
	at org.hibernate.event.def.DefaultFlushEntityEventListener.dirtyCheck(DefaultFlushEntityEventListener.java:520)
	at org.hibernate.event.def.DefaultFlushEntityEventListener.isUpdateNecessary(DefaultFlushEntityEventListener.java:230)
	at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:154)
	at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:219)
	at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:99)
	at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
	at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
	at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:383)
	at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133)
	at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:656)
	... 38 more

save the transient instance before flushing: cn.edu.fjnu.java1.cdio2.yplan.domain.Course
把主控端的cascade 属性修改为”save-update”试试
引用 5 楼 zhangjihao 的回复:

save the transient instance before flushing: cn.edu.fjnu.java1.cdio2.yplan.domain.Course
把主控端的cascade 属性修改为”save-update”试试

问题已经解决了,太大意了。
原因是,虽然我 forum 与course虽然都已经建立和插入数据,但是我topicTest中,插入数据时候,没有去引用course中已经存在的数据主键,编译器报错:让我要先把course这张表先建起来,才可以插topic的数据。


CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明设计多张1对多表的hibernate一对多级联删除