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=?
3、再改下,加上inverse 。 这个其实就是用反向工程自动生成的。(反向工程还是很好用滴!!)
<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