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);
}
}
}