0.pom.xml
...... <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <hibernate-version>3.6.10.Final</hibernate-version> <javassist-version>3.12.1.GA</javassist-version> <slf4j-nop-version>1.6.6</slf4j-nop-version> <mysql-connector-version>5.1.21</mysql-connector-version> </properties> <dependencies> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>${hibernate-version}</version> </dependency> <dependency> <groupId>javassist</groupId> <artifactId>javassist</artifactId> <version>${javassist-version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-nop</artifactId> <version>${slf4j-nop-version}</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql-connector-version}</version> </dependency> </dependencies> ......
1.schema.sql
create table idcard ( iid integer not null, num integer, primary key (iid) ); create table student ( id integer not null auto_increment, name varchar(255), team_id integer, primary key (id) ); create table team ( id integer not null auto_increment, name varchar(255), primary key (id) ); alter table student add index FK8FFE823BEC0561A1 (team_id), add constraint FK8FFE823BEC0561A1 foreign key (team_id) references team (id);
表结构如下图所示。
student表和idcard表实现一对一主键关联,team和student实现一对多关联。
2.Hibernate Configuration File
...... <mapping class="org.fool.model2.Student" /> <mapping class="org.fool.model2.IdCard" /> <mapping class="org.fool.model2.Team" /> ......
3.Hibernate Model Class
IdCard.java
package org.fool.model2; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.OneToOne; import javax.persistence.PrimaryKeyJoinColumn; import javax.persistence.Table; import org.hibernate.annotations.Fetch; import org.hibernate.annotations.FetchMode; import org.hibernate.annotations.GenericGenerator; import org.hibernate.annotations.Parameter; @Entity @Table(name = "idcard") public class IdCard { @Id @GenericGenerator(name = "generator", strategy = "foreign", parameters = @Parameter(name = "property", value = "student")) @GeneratedValue(generator = "generator") @Column(name = "iid") private int id; @Column(name = "num") private int num; @OneToOne(cascade = CascadeType.ALL) @PrimaryKeyJoinColumn @Fetch(FetchMode.SELECT) private Student student; public int getId() { return id; } public void setId(int id) { this.id = id; } public int getNum() { return num; } public void setNum(int num) { this.num = num; } public Student getStudent() { return student; } public void setStudent(Student student) { this.student = student; } }
以上Annotation代码相当于以下的IdCard.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"> <hibernate-mapping> <class name="org.fool.model2.IdCard" table="idcard"> <id name="id" column="iid" type="integer"> <generator class="foreign"> <param name="property">student</param> </generator> </id> <property name="num" column="num" type="integer" /> <one-to-one name="student" class="org.fool.model2.Student" cascade="all" fetch="select"></one-to-one> </class> </hibernate-mapping>
Student.java
package org.fool.model2; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.OneToOne; import javax.persistence.Table; import org.hibernate.annotations.Fetch; import org.hibernate.annotations.FetchMode; @Entity @Table(name = "student") public class Student { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "sid") private int id; @Column(name = "name") private String name; @OneToOne(cascade = CascadeType.ALL, mappedBy = "student") @Fetch(FetchMode.SELECT) private IdCard idCard; @ManyToOne(cascade = CascadeType.ALL) @JoinColumn(name = "team_id") @Fetch(FetchMode.SELECT) private Team team; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public IdCard getIdCard() { return idCard; } public void setIdCard(IdCard idCard) { this.idCard = idCard; } public Team getTeam() { return team; } public void setTeam(Team team) { this.team = team; } }
以上Annotation代码相当于以下的Student.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"> <hibernate-mapping> <class name="org.fool.model2.Student" table="student"> <id name="id" column="sid" type="integer"> <generator class="identity"> </generator> </id> <property name="name" column="name" type="string" /> <one-to-one name="idCard" class="org.fool.model2.IdCard" cascade="all" fetch="select"></one-to-one> <many-to-one name="team" class="org.fool.model2.Team" column="team_id" cascade="all" fetch="select"></many-to-one> </class> </hibernate-mapping>
Team.java
package org.fool.model2; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.OneToMany; import javax.persistence.Table; @Entity @Table(name = "team") public class Team { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "tid") private int id; @Column(name = "name") private String name; @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "team") private Set<Student> students; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Set<Student> getStudents() { return students; } public void setStudents(Set<Student> students) { this.students = students; } }
以上Annotation代码相当于以下的Team.hbm.xml, 其中The mappedBy attribute of @OneToMany annotation behaves the same as inverse = “true” in the xml file.
<?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"> <hibernate-mapping> <class name="org.fool.model2.Team" table="team"> <id name="id" column="tid" type="integer"> <generator class="identity"> </generator> </id> <property name="name" column="name" type="string" /> <set name="students" lazy="false" cascade="all" inverse="true"> <key column="team_id" /> <one-to-many class="org.fool.model2.Student" /> </set> </class> </hibernate-mapping>
最佳实践:如果没有特殊情况,不要使用cascade;特别注意,可能使用cascade的地方一般都是一的一方进行删除时使用;特殊需求才会使用cascade的add,正常情况add方法都是应该有程序员完成添加,一定要先添加一的一方,之后再添加多的一方,不要使用一的一方来维护关系,在配置文件的set标签中可以通过inverse=true来明确不使用一的这一端维护关系。one-to-many在添加和维护关系时比较麻烦,所以在开发中不建议使用one-to-many的单向。
4.Test It
package org.fool.test; import java.util.HashSet; import org.fool.model2.IdCard; import org.fool.model2.Student; import org.fool.model2.Team; import org.fool.util.HibernateUtil; import org.hibernate.Session; import org.hibernate.Transaction; public class HibernateTest3 { public static void main(String[] args) { // insert(); // select(); } public static void insert() { Session session = HibernateUtil.openSession(); Transaction tx = null; try { tx = session.beginTransaction(); Student student1 = new Student(); student1.setName("zhangsan"); IdCard idCard1 = new IdCard(); idCard1.setNum(99988); student1.setIdCard(idCard1); idCard1.setStudent(student1); Student student2 = new Student(); student2.setName("lisi"); IdCard idCard2 = new IdCard(); idCard2.setNum(99977); student2.setIdCard(idCard2); idCard2.setStudent(student2); Team team = new Team(); team.setName("team1"); team.setStudents(new HashSet<Student>()); team.getStudents().add(student1); team.getStudents().add(student2); student1.setTeam(team); student2.setTeam(team); session.save(team); tx.commit(); } catch (Exception e) { e.printStackTrace(); if (null != tx) { tx.rollback(); } } finally { HibernateUtil.closeSession(session); } } public static void select() { Session session = HibernateUtil.openSession(); Transaction tx = null; try { tx = session.beginTransaction(); Team team = (Team) session.get(Team.class, 1); System.out.println(team.getName()); Student student = (Student) session.get(Student.class, 2); System.out.println(student.getName()); tx.commit(); } catch (Exception ex) { ex.printStackTrace(); if (null != tx) { tx.rollback(); } } finally { HibernateUtil.closeSession(session); } } }
5.result
6.Category一对多实现表自关联
shema.sql
alter table category drop foreign key FK302BCFEA51B0EBD; drop table if exists category; create table category (cid bigint not null auto_increment, name varchar(255), category_id bigint, primary key (cid)); alter table category add index FK302BCFEA51B0EBD (category_id), add constraint FK302BCFEA51B0EBD foreign key (category_id) references category (cid);
表结构如下图所示
Category.java
package org.fool.model; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; import javax.persistence.Table; @Entity @Table(name = "category") public class Category { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "cid") private Long id; @Column(name = "name") private String name; @ManyToOne @JoinColumn(name = "category_id") private Category parentCategory; @OneToMany(cascade = CascadeType.ALL, mappedBy = "parentCategory") private Set<Category> childCategories; public Category() { } public Category(String name, Category parentCategory, Set<Category> childCategories) { super(); this.name = name; this.parentCategory = parentCategory; this.childCategories = childCategories; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Category getParentCategory() { return parentCategory; } public void setParentCategory(Category parentCategory) { this.parentCategory = parentCategory; } public Set<Category> getChildCategories() { return childCategories; } public void setChildCategories(Set<Category> childCategories) { this.childCategories = childCategories; } }
以上Annotation代码相当于以下的Category.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"> <hibernate-mapping> <class name="org.fool.model.Category" table="category"> <id name="id" column="cid" type="long"> <generator class="identity"> </generator> </id> <property name="name" column="name" type="string" /> <set name="childCategories" cascade="all" inverse="true"> <key column="category_id" /> <one-to-many class="org.fool.model.Category" /> </set> <many-to-one name="parentCategory" column="category_id" class="org.fool.model.Category"> </many-to-one> </class> </hibernate-mapping>
测试一下
package org.fool.test; import java.util.HashSet; import org.fool.model.Category; import org.fool.util.HibernateUtil; import org.hibernate.Session; import org.hibernate.Transaction; public class HibernateTest2 { public static void main(String[] args) { // insert(); // select(); // delete(); } /** * 添加类别 */ public static void insert() { Session session = HibernateUtil.openSession(); Transaction tx = null; try { tx = session.beginTransaction(); Category category1 = new Category("level1", null, new HashSet<Category>()); Category category2 = new Category("level2", null, new HashSet<Category>()); Category category3 = new Category("level2", null, new HashSet<Category>()); Category category4 = new Category("level3", null, new HashSet<Category>()); Category category5 = new Category("level3", null, new HashSet<Category>()); Category category6 = new Category("level3", null, new HashSet<Category>()); Category category7 = new Category("level3", null, new HashSet<Category>()); category2.setParentCategory(category1); category3.setParentCategory(category1); category1.getChildCategories().add(category2); category1.getChildCategories().add(category3); category4.setParentCategory(category2); category5.setParentCategory(category2); category2.getChildCategories().add(category4); category2.getChildCategories().add(category5); category6.setParentCategory(category3); category7.setParentCategory(category3); category3.getChildCategories().add(category6); category3.getChildCategories().add(category7); session.save(category1); tx.commit(); } catch (Exception ex) { ex.printStackTrace(); if (null != tx) { tx.rollback(); } } finally { HibernateUtil.closeSession(session); } } /** * 查询类别 */ public static void select() { Session session = HibernateUtil.openSession(); Transaction tx = null; try { tx = session.beginTransaction(); Category category = (Category) session.get(Category.class, new Long(1)); System.out.println(category.getChildCategories().iterator().next() .getName()); tx.commit(); } catch (Exception ex) { ex.printStackTrace(); if (null != tx) { tx.rollback(); } } finally { HibernateUtil.closeSession(session); } } /** * 删除类别 */ public static void delete() { Session session = HibernateUtil.openSession(); Transaction tx = null; try { tx = session.beginTransaction(); Category category = (Category) session.get(Category.class, new Long(1)); session.delete(category); tx.commit(); } catch (Exception ex) { ex.printStackTrace(); if (null != tx) { tx.rollback(); } } finally { HibernateUtil.closeSession(session); } } }