1. Create a table with three simple fields.
Primary Key, name, foreign key pointing to its own 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=InnoDBDEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ciAUTO_INCREMENT=1ROW_FORMAT=COMPACT;
2. Classes and ing files.
public class Category implements java.io.Serializable {// Fieldsprivate 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 accessorspublic 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;}}
Then there is the ing file. Let's take a look at the effects of several different configurations.
1. It was originally written as follows:
Test code:
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();
The following error occurs: the order of storage should be caused. How can I create an update statement? Please give answers!
Hibernate: insert into h_01.category (category_id, name) values (?, ?)14Hibernate: 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.Categoryat 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. Change the configuration file to add a cascade.
<set name="categories" cascade="save-update"> <key> <column name="category_id" /> </key> <one-to-many class="modle.Category" /> </set>
The execution is correct, but there are three statements.
Hibernate: insert into h_01.category (category_id, name) values (?, ?)Hibernate: insert into h_01.category (category_id, name) values (?, ?)15Hibernate: update h_01.category set category_id=? where id=?
3. Add inverse. This is actually automatically generated by reverse engineering. (Reverse engineering is still very useful !!)
<set name="categories" inverse="true" cascade="save-update"> <key> <column name="category_id" /> </key> <one-to-many class="modle.Category" /> </set>
That's right. It should be two statements.
Hibernate: insert into h_01.category (category_id, name) values (?, ?)Hibernate: insert into h_01.category (category_id, name) values (?, ?)17