1、建表,很简单的3个字段。
主键,name,外键指向自身id
CREATE TABLE `NewTable` ( `id` int(11) NOT NULL AUTO_INCREMENT , `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL , `category_id` int(11) NULL DEFAULT NULL , PRIMARY KEY (`id`), FOREIGN KEY (`category_id`) REFERENCES `category` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT, INDEX `category_id` (`category_id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci AUTO_INCREMENT=1 ROW_FORMAT=COMPACT ;
2、类以及映射文件。
public class Category implements java.io.Serializable { // Fields private Integer id; private Category category; private String name; private Set categories = new HashSet(0); // Constructors /** default constructor */ public Category() { } /** minimal constructor */ public Category(Category category) { this.category = category; } /** full constructor */ public Category(Category category, String name, Set categories) { this.category = category; this.name = name; this.categories = categories; } // Property accessors public Integer getId() { return this.id; } public void setId(Integer id) { this.id = id; } public Category getCategory() { return this.category; } public void setCategory(Category category) { this.category = category; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } public Set getCategories() { return this.categories; } public void setCategories(Set categories) { this.categories = categories; } }
然后是映射文件。 来看看几种不同的配置会有怎样的效果
1、最初是这样写的:
<hibernate-mapping> <class name="modle.Category" table="category" catalog="h_01"> <id name="id" type="java.lang.Integer"> <column name="id" /> <generator class="identity" /> </id> <many-to-one name="category" class="modle.Category" fetch="select"> <column name="category_id" /> </many-to-one> <property name="name" type="java.lang.String"> <column name="name" length="50" /> </property> <set name="categories"> <key> <column name="category_id" /> </key> <one-to-many class="modle.Category" /> </set> </class> </hibernate-mapping>
测试代码:
Category c1 = new Category();
c1.setCategories(new HashSet());
c1.setCategory(null);
c1.setName("c1");
Category c2 = new Category();
c2.setCategory(c1);
c2.setName("c2");
c2.setCategories(null);
c1.getCategories().add(c2);
Session session = HibernateSessionFactory.getSession();
Transaction tran = session.beginTransaction();
session.save(c1);
System.out.println(c1.getId());
tran.commit();
session.close();
出现了下面的错误:应该是保存顺序导致,怎么还有一个update语句呢? 请高手解答!
Hibernate: insert into h_01.category (category_id, name) values (?, ?) 14 Hibernate: update h_01.category set category_id=? where id=? Exception in thread "main" org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: modle.Category at org.hibernate.engine.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:242) at org.hibernate.type.EntityType.getIdentifier(EntityType.java:430) at org.hibernate.type.ManyToOneType.nullSafeSet(ManyToOneType.java:101) at org.hibernate.persister.collection.AbstractCollectionPersister.writeElement(AbstractCollectionPersister.java:777) at org.hibernate.persister.collection.AbstractCollectionPersister.recreate(AbstractCollectionPersister.java:1165)
2、然后改下配置文件 添加一个cascade
<set name="categories" cascade="save-update"> <key> <column name="category_id" /> </key> <one-to-many class="modle.Category" /> </set>
执行正确,但是有3条语句。
Hibernate: insert into h_01.category (category_id, name) values (?, ?) Hibernate: insert into h_01.category (category_id, name) values (?, ?) 15 Hibernate: update h_01.category set category_id=? where id=?
<set name="categories" inverse="true" cascade="save-update"> <key> <column name="category_id" /> </key> <one-to-many class="modle.Category" /> </set>这就对了,应该是两条语句。
Hibernate: insert into h_01.category (category_id, name) values (?, ?) Hibernate: insert into h_01.category (category_id, name) values (?, ?) 17