前奏:以学生和班级为例,学生和班级是一对多的关系,所谓一对多双项,是指可以通过班级找到学生并操作学生,学生也可以反过来操作班级,本例子用注解方式实现一对多双项,采用的仍然是MySQL数据库
实体类:学生类 Student.java
package com.web0819;
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.Table;
@Entity
@Table(name = "student")
public class Student {
@Id
@Column(name = "sid")
@GeneratedValue(strategy = GenerationType.AUTO)
private int sid;
@Column(name = "name", length = 20)
private String name;
@ManyToOne(cascade={CascadeType.ALL})
@JoinColumn(name="cid")
private Classes classes;
public Classes getClasses() {
return classes;
}
public void setClasses(Classes classes) {
this.classes = classes;
}
public int getSid() {
return sid;
}
public void setSid(int sid) {
this.sid = sid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Student() {
}
public Student(int sid, String name) {
this.sid = sid;
this.name = name;
}
@Override
public String toString() {
return "Student [sid=" + sid + ", name=" + name + "]";
}
}
实体类:班级类 Classes.java
package com.web0819;
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.OneToMany;
import javax.persistence.Table;
@Entity
@Table(name = "classes")
public class Classes {
@Id
@Column(name = "cid")
@GeneratedValue(strategy = GenerationType.AUTO)
private int cid;
@Column(name = "name", length = 20)
private String name;
// 指定一对多关系
@OneToMany(cascade = { CascadeType.ALL },mappedBy="classes")
private Set<Student> students;
public int getCid() {
return cid;
}
public void setCid(int cid) {
this.cid = cid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@OneToMany(cascade = { CascadeType.ALL }, mappedBy = "classes")
public Set<Student> getStudents() {
return students;
}
public void setStudents(Set<Student> students) {
this.students = students;
}
public Classes() {
}
public Classes(int cid, String name, Set<Student> students) {
this.cid = cid;
this.name = name;
this.students = students;
}
}
配置文件:hibernate.cfg.xml
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- 链接数据库的用户名 -->
<property name="connection.username">root</property>
<!-- 链接数据库的密码 -->
<property name="connection.password">lixin123</property>
<!-- 链接数据库的驱动 -->
<property name="connection.driver_class">
com.mysql.jdbc.Driver
</property>
<!-- 链接数据库的url -->
<property name="connection.url">
jdbc:mysql://localhost:3306/test
</property>
<!--
方言
告诉hibernate使用什么样的数据库,hibernate就会在底层拼接什么样的sql语句
-->
<property name="dialect">
org.hibernate.dialect.MySQLDialect
</property>
<!--
根据持久化类生成表的策略
validate 通过映射文件检查持久化类与表的匹配
update 每次hibernate启动的时候,检查表是否存在,如果不存在,则创建,如果存在,则什么都不做了
create 每一次hibernate启动的时候,根据持久化类和映射文件生成表
create-drop
-->
<property name="hbm2ddl.auto">update</property>
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<mapping class="com.web0819.Classes" />
<mapping class="com.web0819.Student" />
</session-factory>
</hibernate-configuration>
测试工具类:HibernateUtils.java
package com.web0819;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
public class HibernateUtils {
private static SessionFactory sessionFactory;
private static ServiceRegistry serviceRegistry;
public static SessionFactory getSessionFactory() {
Configuration configuration = new Configuration();
configuration.configure();
serviceRegistry = new ServiceRegistryBuilder().applySettings(
configuration.getProperties()).buildServiceRegistry();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
return sessionFactory;
}
}
测试类:HibernateTest.java
package com.web0819;
import java.util.HashSet;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
public class HibernateTest {
@Test
public void test1(){
// 测试SessionFactory 和session配置
Session s = HibernateUtils.getSessionFactory().openSession();
System.out.println(s);
}
@Test
public void test2(){
// 添加班级
Session s = HibernateUtils.getSessionFactory().openSession();
Transaction transaction = s.beginTransaction();
Classes classes = new Classes();
classes.setName("1班");
s.save(classes);
transaction.commit();
s.close();
}
@Test
public void test3(){
// 添加学生
Session s = HibernateUtils.getSessionFactory().openSession();
Transaction transaction = s.beginTransaction();
Student student = new Student();
student.setName("小明");
s.save(student);
transaction.commit();
s.close();
}
@Test
public void test4(){
// 添加班级 建立学生和班级的关系 只保存班级
Session s = HibernateUtils.getSessionFactory().openSession();
Transaction transaction = s.beginTransaction();
// 新建班级
Classes classes = new Classes();
classes.setName("3班");
// 新建学生
Student student = new Student();
student.setName("小花");
HashSet<Student> students = new HashSet<Student>();
students.add(student);
//建立关系
classes.setStudents(students);
student.setClasses(classes); //如果不写这句话的话 学生的外键会是null
//只保存班级
s.save(classes);
transaction.commit();
}
@Test
public void test5(){
// 添加班级 从数据库中取得学生 建立和班级的关系 保存班级
Session s = HibernateUtils.getSessionFactory().openSession();
Transaction transaction = s.beginTransaction();
// 新建班级
Classes classes = new Classes();
classes.setName("4班");
// 取得学生
Student student = (Student) s.get(Student.class, 1);
//建立关系
HashSet<Student> students = new HashSet<Student>();
students.add(student);
classes.setStudents(students);
student.setClasses(classes);
//只保存班级
s.save(classes);
transaction.commit();
}
@Test
public void test6(){
// 添加学生 从数据库中取得班级 建立和班级的关系 更新班级
Session s = HibernateUtils.getSessionFactory().openSession();
Transaction transaction = s.beginTransaction();
// 获取班级
Classes classes =(Classes) s.get(Classes.class, 1);
// 新建学生
Student student = new Student();
student.setName("小红");
//建立关系
student.setClasses(classes);
classes.getStudents().add(student);
//只保存班级
s.update(classes);
transaction.commit();
}
@Test
public void test7(){
// 从数据库中取得班级 和学生 改变学生的班级 只更新班级
Session s = HibernateUtils.getSessionFactory().openSession();
Transaction transaction = s.beginTransaction();
// 获取班级
Classes classes =(Classes) s.get(Classes.class, 1);
// 获取学生
Student student = (Student) s.get(Student.class, 1);
//建立关系
student.setClasses(classes);
classes.getStudents().add(student);
//只保存班级
s.update(classes);
transaction.commit();
}
@Test
public void test8(){
// 从数据库中取得班级 清空该班所有学生
Session s = HibernateUtils.getSessionFactory().openSession();
Transaction transaction = s.beginTransaction();
// 获取班级
Classes classes =(Classes) s.get(Classes.class, 1);
//建立关系 清空学生
for (Student student : classes.getStudents()) {
student.setClasses(null);
}
//只保存班级
s.update(classes);
transaction.commit();
}
@Test
public void test9(){
// 从数据库中取得班级 删除班级和班级里的学生 只删除班级
Session s = HibernateUtils.getSessionFactory().openSession();
Transaction transaction = s.beginTransaction();
// 获取班级
Classes classes =(Classes) s.get(Classes.class, 1);
s.delete(classes);
transaction.commit();
}
@Test
public void test10(){
// 新建学生 新建班级 建立关系 只保存学生级联保存班级
Session session = HibernateUtils.getSessionFactory().openSession();
Transaction transaction = session.beginTransaction();
// 新建学生
Student student = new Student();
student.setName("a");
//新建班级
Classes classes = new Classes();
classes.setName("1班");
//建立关系
student.setClasses(classes);
session.save(student);
transaction.commit();
session.close();
}
@Test
public void test11(){
// 新建学生 获取班级 建立关系 只保存学生级联保存班级
Session session = HibernateUtils.getSessionFactory().openSession();
Transaction transaction = session.beginTransaction();
// 新建学生
Student student = new Student();
student.setName("b");
//获取班级
Classes classes =(Classes) session.get(Classes.class, 10);
//建立关系
student.setClasses(classes);
classes.getStudents().add(student);
session.save(student);
transaction.commit();
session.close();
}
@Test
public void test12(){
// 获取学生 获取班级 改变关系 只保存学生级联更新班级
Session session = HibernateUtils.getSessionFactory().openSession();
Transaction transaction = session.beginTransaction();
// 获取学生
Student student = (Student) session.get(Student.class, 10);
//获取班级
Classes classes =(Classes) session.get(Classes.class, 8);
//建立关系
student.setClasses(classes);
classes.getStudents().add(student);
session.save(student);
transaction.commit();
session.close();
}
@Test
public void test13(){
// 删除班级 级联删除学生
Session session = HibernateUtils.getSessionFactory().openSession();
Transaction transaction = session.beginTransaction();
//获取班级
Classes classes =(Classes) session.get(Classes.class, 8);
session.delete(classes);
transaction.commit();
session.close();
}
}
小结:学生和班级是一对多的关系,学生是多的一方,班级是一的一方,所以在Student类中设置一个属性是Classes classes,在班级类中设置一个属性Set students,这样才能双向关联。
对于注解的配置,在Student类中的classes这没别的说的,以为是对于学生来说是多对一,所以manytoone,@JoinColumn是外键。对于Classes类,对于班级来说是一对多,所以在set集合上配置oneotomany,注意onetomany里面有个属性是mappedby,翻译为中文是由。。。映射,这个属性比较复杂
首先,mappedBy这个注解只能够用在@OntToOne,@OneToMany,@manyToMany中,不能够用在@manyToOne中;
第二,这个注解看网上的意思可以简单地理解为:这个注解用在主表的一方,就是被引用的一方;
第三,这个注解是与@JoinColumn这个注解是互斥的,因为@JoinColumn这个注解使用在拥有外键的表的一方,就是从表的一方。
第四,这个注解的属性值是:指向另外一个类中定义的一个属性,这个属性的类型是当前这个类;有点绕,有点晕,是的;就是说它的属性值指向的是:与之关联类中定义的指向本类的一个属性!