文章目录
@Entity
@Table(name="husband")
public class Husband {
private int id;
private String name;
private int age;
@Id
@GeneratedValue //主键生成策略,自增长
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(length=20) //设置长度为20
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Husband [id=" + id + ", name=" + name + ", age=" + age + "]";
}
}
@Entity
@Table(name="wife")
public class Wife {
private int id;
private String name;
private int age;
@Id
@GeneratedValue //主键生成策略,自增长
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(length=20) //设置长度为20
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Husband [id=" + id + ", name=" + name + ", age=" + age + "]";
}
}
个
select * from husband h join wife w on h.wife_id=w.id;
类名小写_id
,但是我们可以使用@JoinColumn(name="")
改变外键的名称import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;
@Entity //指定实体类
@Table(name="husband") //指定对应数据库的表名为husband
public class Husband {
private int id;
private String name;
private int age;
private Wife Wife;
@Id
@GeneratedValue //主键生成策略,自增长
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@OneToOne //设置wife的主键为Husband的外键,默认的对应表中的字段为wife_id
@JoinColumn(name="wifeid") // 默认外键的名字为wife_id.我们使用这个注解改变外键的名字为wifeid
public Wife getWife() {
return Wife;
}
public void setWife(Wife wife) {
Wife = wife;
}
@Column(length=20) //设置长度为20
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Husband [id=" + id + ", name=" + name + ", age=" + age + "]";
}
}
hibernate.cfg.xml
添加实体类的映射即可
<mapping class="cn.tedu.bean.Husband"></mapping>
<mapping class="cn.tedu.bean.Wife"></mapping>
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import cn.tedu.bean.Husband;
import cn.tedu.bean.Teacher;
import cn.tedu.bean.Wife;
import cn.tedu.utils.HibernateUntil;
public class TestOneToOne {
/**
* 添加数据到husband中
*/
@Test
public void TestAdd() {
Session session = null;
Transaction transaction = null;
try {
// 创建session
session = HibernateUntil.getSession();
// 开始事务
transaction = session.beginTransaction();
//创建wife对象,并且设置属性值,由于主键是自增长的,因此这里不需要自己设置
Wife wife=new Wife();
wife.setAge(22);
wife.setName("Marry");
//新建husband对象
Husband husband=new Husband();
husband.setAge(22);
husband.setName("陈加兵");
//将Wife的对象添加到Husband中,如果这里设置了级联操作,那么只需要保存husband对象即可完成wife的数据保存
husband.setWife(wife);
//由于没有设置级联操作,因此这里需要先保存wife对象,否则将不能在数据库中添加成功
session.save(wife);
//保存丈夫的信息
session.save(husband);
// 提交事务
transaction.commit();
} catch (Exception exception) {
transaction.rollback(); // 事务回滚
} finally {
if (session!=null) {
session.close();
}
}
}
/**
* 查询丈夫和对应妻子的信息
* 根据id查询,只要查询到丈夫的对象,那么妻子的信息就会保存在Husband的属性Wife对象中,因此可以通过访问其中的wife属性来获取对应妻子的信息
* 原理:使用session.get(class<T> cls,id),其实发出的sql语句是外连接语句:
* select * from husband h left join wife w on h.wifeid=w.id where h.id=?
* 如果能够查找到对应的妻子信息就将其添加到Husband中的wife属性中,如果没有查找到那么设置wife属性为null即可,这个就是外连接
*/
@Test
public void TestGet() {
Session session = null;
Transaction transaction = null;
try {
// 创建session
session = HibernateUntil.getSession();
// 开始事务
transaction = session.beginTransaction();
//查询id=1的husband信息
Husband husband=session.get(Husband.class, 1);
//获取对应的妻子对象
Wife wife=husband.getWife();
//输出
System.out.println(husband);
System.out.println(wife);
// 提交事务
transaction.commit();
} catch (Exception exception) {
transaction.rollback(); // 事务回滚
} finally {
if (session!=null) {
session.close();
}
}
}
/**
* 测试修改操作: 这里我们修改id=1的Husband对应的妻子的信息为id=2,当然前提是id=2的wife信息要存在,否则将不会成功
* 想要修改妻子的数据,直接修改Husband中的wife属性即可
*/
@Test
public void TestUpdate() {
Session session = null;
Transaction transaction = null;
try {
// 创建session
session = HibernateUntil.getSession();
// 开始事务
transaction = session.beginTransaction();
//查询id=1的husband信息
Husband husband=session.get(Husband.class, 1);
//查询wife的id=2的对象
Wife wife=session.get(Wife.class, 2);
//如果这个对象查询到
if (wife!=null) {
husband.setWife(wife); //修改Husband对象中的wife属性值即可
}
session.update(husband); //执行更新操作
//获取对应的妻子对象
// 提交事务
transaction.commit();
} catch (Exception exception) {
transaction.rollback(); // 事务回滚
} finally {
if (session!=null) {
session.close();
}
}
}
/**
* 测试删除wife表中的数据
* 原理: 如果设置了外键关联,那么我们想要删除wife的数据,必须先要删除其中与之外键关联的丈夫的信息,或者设置Husband表中的外键为其他的wife数据
* 两种解决办法:
* 1. 先删除对应的丈夫的数据
* 2. 直接将丈夫对应的表的wifeId设置为其他或者为空即可
*
* 下面我们使用的是设置丈夫对应的wifeId为空,那么就可以删除其对应的妻子的数据
*/
@Test
public void TestDelete() {
Session session = null;
Transaction transaction = null;
try {
// 创建session
session = HibernateUntil.getSession();
// 开始事务
transaction = session.beginTransaction();
//查询到id=2的wife数据
Wife wife=session.get(Wife.class,2);
//查询其对应的丈夫,这里还没有讲到其他的查询条件,所以我们默认id=2就是wife的id=2的对应的丈夫
Husband husband=session.get(Husband.class, 2);
//将wife设置null,表示将wifeId外键设置空,因此就断了外键关联
husband.setWife(null);
//删除wife
session.delete(wife);
// 提交事务
transaction.commit();
} catch (Exception exception) {
transaction.rollback(); // 事务回滚
} finally {
if (session!=null) {
session.close();
}
}
}
}
Wife
类
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;
@Entity
@Table(name="wife")
public class Wife {
private int id;
private String name;
private int age;
private Husband husband;
@Id
@GeneratedValue //主键生成策略,自增长
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@OneToOne //设置丈夫的主键为妻子外键
@JoinColumn(name="husbandId") // 外键名称为husbandId
public Husband getHusband() {
return husband;
}
public void setHusband(Husband husband) {
this.husband = husband;
}
@Column(length=20) //设置长度为20
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Husband [id=" + id + ", name=" + name + ", age=" + age + "]";
}
}
OneToOne
注解即可,就表示这个对象的主键会作为该实体类的外键OneToOne
注解,但是我们使用了OneToOne就会在两张表中都会将对方的主键作为自己的外键,显然是没有必要的,冗余。mappedBy
,或者在想要成为对方的外键的类中的对方的对象的get方法中添加即可。
mappedBy=”“
,其中的值一定要和该类对象对方类中属性的字段相同
mappedBy
添加到Wife类中的Husband对象的get方法头上即可
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;
@Entity //指定实体类
@Table(name="husband") //指定对应数据库的表名为husband
public class Husband {
private int id;
private String name;
private int age;
private Wife Wife; //Wife对象
@Id
@GeneratedValue //主键生成策略,自增长
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@OneToOne //设置wife的主键为Husband的外键,默认的对应表中的字段为wife_id
@JoinColumn(name="wifeid") // 默认外键的名字为wife_id.我们使用这个注解改变外键的名字为wifeid
public Wife getWife() {
return Wife;
}
public void setWife(Wife wife) {
Wife = wife;
}
@Column(length=20) //设置长度为20
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Husband [id=" + id + ", name=" + name + ", age=" + age
+ ", Wife=" + Wife + "]";
}
}
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;
@Entity
@Table(name="wife")
public class Wife {
private int id;
private String name;
private int age;
private Husband husband; //Husband对象
@Id
@GeneratedValue //主键生成策略,自增长
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
/**
* mappedBy="对方类中的该类的属性名字",注意这里的名字和一定要和对方类中的成员变量的字段一样
* 表示将维护权交给对方类中的当前类的对象,就是表示当前类的主键将会作为外键
*/
@OneToOne(mappedBy="wife") //设置关联,并且将维护权交给了对方类中的属性wife,因此这里的外键就是wifeId
public Husband getHusband() {
return husband;
}
public void setHusband(Husband husband) {
this.husband = husband;
}
@Column(length=20) //设置长度为20
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Wife [id=" + id + ", name=" + name + ", age=" + age
+ ", husband=" + husband + "]";
}
}
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;
@Entity
@Table(name="wife")
public class Wife {
private int id;
private String name;
private int age;
private Husband husband; //Husband对象
@Id
@GeneratedValue //主键生成策略,自增长
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
/**
* mappedBy="对方类中的该类的属性名字",注意这里的名字和一定要和对方类中的成员变量的字段一样
* 表示将维护权交给对方类中的当前类的对象,就是表示当前类的主键将会作为外键
*/
@OneToOne(mappedBy="wife") //设置关联,并且将维护权交给了对方类中的属性wife,因此这里的外键就是wifeId
public Husband getHusband() {
return husband;
}
public void setHusband(Husband husband) {
this.husband = husband;
}
@Column(length=20) //设置长度为20
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Wife [id=" + id + ", name=" + name + ", age=" + age
+ ", husband=" + husband + "]";
}
}
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="student")
public class Student {
private int id; //主键
private String name;
private int age;
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(length=10)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
/**
* 一个宿舍可以被多个学生住
* 一个学生只能住在一个宿舍
* 学生是One
* 宿舍是Many
*/
public class Dormitory {
private int id; //主键
private Long number; //宿舍编号
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Long getNumber() {
return number;
}
public void setNumber(Long number) {
this.number = number;
}
}
@Entity
@Table(name = "dormitory")
public class Dormitory {
private int id; // 主键
private Long number; // 宿舍编号
private Set<Student> students;
@Id
@GeneratedValue
public int getId() {
return id;
}
@OneToMany //Dormitory是One的一方,Student是Many的一方,因此这里使用OneToMany
@JoinColumn(name="dormitory_id") //必须指定外键的名称,否则将会自动创建第三张表来管理关联关系
public Set<Student> getStudents() {
return students;
}
public void setStudents(Set<Student> students) {
this.students = students;
}
public void setId(int id) {
this.id = id;
}
public Long getNumber() {
return number;
}
public void setNumber(Long number) {
this.number = number;
}
}
@Test
public void TestGet() {
Session session = null;
Transaction transaction = null;
try {
// 创建session
session = HibernateUntil.getSession();
// 开始事务
transaction = session.beginTransaction();
Dormitory dormitory=new Dormitory();
dormitory.setNumber(10011L);
//创建一个Set集合存储Student对象
Set<Student> students=new HashSet<Student>();
for(int i=0;i<5;i++){
Student student=new Student();
student.setAge(10*i);
student.setName("name_"+i);
session.save(student);
students.add(student); // 添加到集合中
}
dormitory.setStudents(students); //将学生信息添加到宿舍对象中
session.save(dormitory); //保存宿舍信息
// 提交事务
transaction.commit();
} catch (Exception exception) {
transaction.rollback(); // 事务回滚
} finally {
if (session != null) {
session.close();
}
}
}
@Entity
@Table(name="student")
public class Student {
private int id; //主键
private String name;
private int age;
private Dormitory dormitory; //添加Dormitory对象,因为是One的一方,因此不用Set集合存储
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@ManyToOne //使用@ManyToOne,因为Student是Many的一方
@JoinColumn(name="dormitory_id") //设置外键的字段值
public Dormitory getDormitory() {
return dormitory;
}
public void setDormitory(Dormitory dormitory) {
this.dormitory = dormitory;
}
@Column(length=10)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
@OneToMany
上加上mappedBy
属性即可。
@OneToMany
这个注解中添加mappedBy
这个属性即可
@JoinColumn()
设置外键的字段名
@Entity
@Table(name="student")
public class Student {
private int id; //主键
private String name;
private int age;
private Dormitory dormitory; //添加Dormitory对象,因为是One的一方,因此不用Set集合存储
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@ManyToOne //使用@ManyToOne,因为Student是Many的一方
@JoinColumn(name="dormitory_id") //设置外键的字段值,因为外键是在student表中添加的,因此只能在这个地方设置外键的字段名
public Dormitory getDormitory() {
return dormitory;
}
public void setDormitory(Dormitory dormitory) {
this.dormitory = dormitory;
}
@Column(length=10)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
@Entity
@Table(name = "dormitory")
public class Dormitory {
private int id; // 主键
private Long number; // 宿舍编号
private Set<Student> students;
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
//仍然需要注意的是mappedBy的值必须是对方类中该类对象的一样的字段
@OneToMany(mappedBy="dormitory") //添加注解,由于是双向外键关联,必须添加mappedBy,由于外键就是One的一方的主键,因此这里的只需要在OneToMany中添加即可
public Set<Student> getStudents() {
return students;
}
public void setStudents(Set<Student> students) {
this.students = students;
}
public Long getNumber() {
return number;
}
public void setNumber(Long number) {
this.number = number;
}
}
@OneToMany
这个注解。如果想要通过Many的一方获取One的数据,那么需要在Many的实体类中添加One的实体类的对象为其成员变量,同时在这个成员变量的get方法上使用@ManyToOne
这个注解
@JoinColumn
改变外键的字段名,那么必须在One的实体类中使用,因为外键是设置在One的一方的表中
@OneToMany(mappedBy=)
设置主导地位的表,如果不设置这个mappedBy,那么就会出现双向外键,出现了冗余
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="teacher")
public class Teacher {
private int id; //主键
private String name;
private int age;
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(length=10)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="student")
public class Student {
private int id; //主键
private String name;
private int age;
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(length=10)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
@Entity
@Table(name="student")
public class Student {
private int id; //主键
private String name;
private int age;
private Set<Teacher> teachers;
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@ManyToMany
//指定第三张表的名称,如果默认的是student_teacher,joinColumns指定的是当前的实体类的外键名称,inverseJoinColumns指定的是另外一个实体类的外键名称
//如果不指定外键的名称,那么默认的是student_id,和teacher_id
@JoinTable(name="stu_tea",joinColumns=@JoinColumn(name="st_id"),inverseJoinColumns=@JoinColumn(name="t_id"))
public Set<Teacher> getTeachers() {
return teachers;
}
public void setTeachers(Set<Teacher> teachers) {
this.teachers = teachers;
}
@Column(length=10)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
表名_表名
,但是我们可以使用@JoinTable
这个注解来修改第三张表的名称name
属性可以修改joinColumns
指定的是当前的实体类对应的外键名称,其中的值使用的@JoinColumn
注解inverseJoinColumns
指定的是另外一个实体类的外键名称,其中的值使用的是@JoinColumn
注解get
方法上使用@ManyToMany
mappedBy
)否则的话就会出现冗余,因此一定要指定主导关系。
mappedBy
属性
@Entity
@Table(name="student")
public class Student {
private int id; //主键
private String name;
private int age;
private Set<Teacher> teachers;
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@ManyToMany
//指定第三张表的名称,如果默认的是student_teacher,joinColumns指定的是当前的实体类的外键名称,inverseJoinColumns指定的是另外一个实体类的外键名称
//如果不指定外键的名称,那么默认的是student_id,和teacher_id
@JoinTable(name="stu_tea",joinColumns=@JoinColumn(name="st_id"),inverseJoinColumns=@JoinColumn(name="t_id"))
public Set<Teacher> getTeachers() {
return teachers;
}
public void setTeachers(Set<Teacher> teachers) {
this.teachers = teachers;
}
@Column(length=10)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
@Entity
@Table(name="teacher")
public class Teacher {
private int id; //主键
private String name;
private int age;
private Set<Student> students;
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@ManyToMany(mappedBy="teachers") //将维护权交给teacher表,这里的teachers是Student类中的字段名,一定要一模一样的
public Set<Student> getStudents() {
return students;
}
public void setStudents(Set<Student> students) {
this.students = students;
}
@Column(length=10)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- 必须要配置的5大参数,4大参数,一个方言 其中的四大参数是连接JDBC必须的参数 这里的方言也是必须的 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hirbernate</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>
<!-- mysql的方言 -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 可选的配置文件 -->
<!-- 输出所有的sql语句到控制台 -->
<property name="hibernate.show_sql">true</property>
<!-- 在控制台上打印出漂亮的sql语句 -->
<property name="hibernate.format_sql">true</property>
<!-- 配置如果这个表还没有创建,那么就会自动创建,如果已经创建了,那么会自动更新 -->
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 配置不生成Hibernate_sequence -->
<property name="hibernate.id.new_generator_mappings">false</property>
<!-- 直接指定这个Teacher实体类的全类名即可,即是完成了映射 -->
<mapping class="cn.tedu.bean.Student"></mapping>
<mapping class="cn.tedu.bean.Teacher"></mapping>
</session-factory>
</hibernate-configuration>
mappedBy
指定外键的维护权,否则将会出现数据冗余@JoinColumn
这个注解来设置外键的字段名,但是在多对多的关系中,因为需要第三张表来维护,因此要使用@JoinTable
这个注解来设置外键和第三张表的一些属性