对象关系 - 多对一
一对一就好比一个班级对应一个班主任,而一个班主任也只管理一个班级
多对一就好比班级和学生的关系,一个班级有很多学生,很多的学生组成一个班级
由于一对一比较简单,再此就不过多解释了,接下来先用一个项目来讲解多对一
来做一个hibernate多对一的增删改查
JavaBean代码多端:学生
//一个班级有好多学生
public class Student {// manytoOne
private int sid;
private String sname;
private int age;
private double score;
// 关联属性
private Clazz clazz;
public Student() {
}
public int getSid() {
return sid;
}
public void setSid(int sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
public Clazz getClazz() {
return clazz;
}
public void setClazz(Clazz clazz) {
this.clazz = clazz;
}
@Override
public String toString() {
return "Student [sid=" + sid + ", sname=" + sname + ", age=" + age + ", score=" + score + ", clazz=]"
;
}
}
JavaBean代码一端: Clazz班级,由于是单向的,故此看不见多端的详情
public class Clazz {//onetomany
private int cid;
private String cname;
public Clazz() {
}
public int getCid() {
return cid;
}
public void setCid(int cid) {
this.cid = cid;
}
public String getCname() {
return cname;
}
public void setCname(String cname) {
this.cname = cname;
}
@Override
public String toString() {
return "Clazz [cid=" + cid + ", cname=" + cname + "]";
}
}
核心配置文件hiernate.cfg.xml
<?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>
<!-- DB四要素 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.password">1234</property>
<property name="hibernate.connection.url">jdbc:mysql:///bwie</property>
<property name="hibernate.connection.username">root</property>
<!--方言 -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
<!-- 配置数据源 -->
<property name="hibernate.connection.provider_class">
org.hibernate.connection.C3P0ConnectionProvider
</property>
<!--生成sql-->
<property name="hibernate.hbm2ddl.auto">update</property>
<!--展示sql -->
<property name="hibernate.show_sql">true</property>
<!--格式化sql -->
<property name="hibernate.format_sql">true</property>
<!-- sesssion上下文 -->
<property name="hibernate.current_session_context_class">thread</property>
<!--关联 映射文件 -->
<!-- !!!重点注意哦!!! -->
<mapping resource="com/baidu/bean/Student.hbm.xml"/>
<mapping resource="com/baidu/bean/Clazz.hbm.xml"/>
</session-factory>
</hibernate-configuration>
关联配置文件:clazz端
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2018-11-14 16:26:37 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
<class name="com.baidu.bean.Clazz" table="t_clazz">
<id name="cid" type="int">
<column name="cid" />
<generator class="native" />
</id>
<property name="cname" type="java.lang.String">
<column name="CNAME" />
</property>
</class>
</hibernate-mapping>
关联配置文件学生端Student.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.baidu.bean">
<class name="Student" table="t_student">
<id name="sid" type="int">
<column name="sid" />
<generator class="native" />
</id>
<property name="sname" type="java.lang.String">
<column name="SNAME" />
</property>
<property name="age" type="int">
<column name="AGE" />
</property>
<property name="score" type="double">
<column name="SCORE" />
</property>
<many-to-one name="clazz" class="Clazz" fetch="join" cascade="save-update" lazy="false">
<!-- 外键字段名称 -->
<!-- !!!重点注意部分!!! -->
<column name="cid" />
</many-to-one>
</class>
</hibernate-mapping>
Dao层代码如下:
public interface StudentDao {
// 添加学生
public int insertStudent(Student stu);
// 删除学生
public int deleteStudentById(int id);
// 修改学生
public int updateStudent(Student stu);
// 查询学生
public Student selectStudentById(int sid);
// 查询所有信息
public List<Student> selectAll();
}
Dao实现类代码:
public class StudentDaoImpl implements StudentDao {
@Override
public int insertStudent(Student stu) {
// 获取session
Session session = HbnUtil.getSession();
// 开启事务
session.getTransaction().begin();
// 添加对象
session.save(stu);
// 提交事务
session.getTransaction().commit();
return 1;
}
@Override
public int deleteStudentById(int id) {
// 获取session
Session session = HbnUtil.getSession();
// 开启事务
session.getTransaction().begin();
// 获取对象
Student stu = session.get(Student.class, id);
// 删除对象
session.delete(stu);
// 提交事务
session.getTransaction().commit();
return 1;
}
@Override
public int updateStudent(Student stu) {
// 获取session
Session session = HbnUtil.getSession();
// 开启事务
session.getTransaction().begin();
// 删除对象
session.update(stu);
// 提交事务
session.getTransaction().commit();
return 1;
}
@Override
public Student selectStudentById(int sid) {
// 获取session
Session session = HbnUtil.getSession();
// 开启事务
session.getTransaction().begin();
// 删除对象
Student stu = session.get(Student.class, sid);
// 提交事务
session.getTransaction().commit();
// 返回目标对象
return stu;
}
@Override
public List<Student> selectAll() {
// 获取session
Session session = HbnUtil.getSession();
// 开启事务
session.beginTransaction();
//准备sql
String hql="from Student";
List<Student> list = session.createQuery(hql).list();
// 提交事务
session.getTransaction().commit();
// 返回目标对象
return list;
}
}
Service层代码的如下:
public interface StudentService {
// 添加学生
public int addStudent(Student stu);
// 删除学生
public int removeStudentById(int id);
// 修改学生
public int changeStudent(Student stu);
// 查询学生
public Student queryStudentById(int sid);
// 查询所有信息
public List<Student> queryAll();
}
Service层的实现代码如下:
public class StudentServiceImpl implements StudentService {
// 引入dao
private StudentDao studentDao;
// 构造器注入
public StudentServiceImpl(StudentDao studentDao) {
this.studentDao = studentDao;
}
@Override
public int addStudent(Student stu) {
return studentDao.insertStudent(stu);
}
@Override
public int removeStudentById(int id) {
return studentDao.deleteStudentById(id);
}
@Override
public int changeStudent(Student stu) {
return studentDao.updateStudent(stu);
}
@Override
public Student queryStudentById(int sid) {
return studentDao.selectStudentById(sid);
}
@Override
public List<Student> queryAll() {
return studentDao.selectAll();
}
}
工具类代码如下:HbnUtil.java
public class HbnUtil {
// 线程安全,可以当做成员对象共享给各个成员;
public static SessionFactory sessionFactory;
/**
* 获取sessionFactory对象
* @return
*/
public static SessionFactory getSessionFactory() {
if (sessionFactory == null || sessionFactory.isClosed()) {
return new Configuration().configure().buildSessionFactory();
} else {
return sessionFactory;
}
}
/**
* 获取session
*
* @return
*/
public static Session getSession() {
// 调用方法
return getSessionFactory().getCurrentSession();
}
}
测试代码如下:增删改查的测试都是OK
public class MyTest {
public StudentDao sDao = new StudentDaoImpl();
public StudentService uService = new StudentServiceImpl(sDao);
@Test
public void testAdd() {
// 添加操作
Student stu = new Student();
stu.setSname("王五");
stu.setScore(90);
stu.setAge(20);
// 实例化班级表
Clazz clz = new Clazz();
clz.setCname("中级班");
// 多端维护外键
stu.setClazz(clz);
// 添加对象
uService.addStudent(stu);
}
@Test
public void testDel() {
// 删除操作
int x = uService.removeStudentById(1);
// 判断
if (x > 0) {
System.out.println("删除成功了");
}
}
@Test
public void testUpdate() {
Clazz clz = new Clazz();
clz.setCid(1);
clz.setCname("加强班");
Student stu = new Student();
stu.setSname("张万年");
stu.setScore(87);
stu.setAge(10);
stu.setSid(4);
// 多端维护外键
stu.setClazz(clz);
// 删除操作
int x = uService.changeStudent(stu);
// 判断
if (x > 0) {
System.out.println("修改成功了");
}
}
@Test
public void testFindOne() {
// 查询操作
Student stu = uService.queryStudentById(3);
// 展示对象信息
System.out.println(stu);
}
@Test
public void testFindAll() {
// 查询操作
List<Student> list = uService.queryAll();
// 遍历容器
for (Student stu : list) {
// 展示对象信息
System.out.println(stu);
}
}
}
注意事项:
主键的生成策略,常见的要知道其特点
Native,默认是自己维护;手动插入
Cascade:no,all,save-update,persister,外键的维护,一般推荐多端来维护;
在many-to-one中lazy的值的含义;
Proxy:
No-proxy:
False:立即加载
在ono-to-many中lazy中的值含义:
True:延迟加载
False:立即加载
Extra:增强加载
Cascade:级联:
No:不做级联操作
All:所有都做级联操作
Save-update,添加,修改时候做级联
Delete:级联删除
sessionFactory.openSession();
sessionFactory.getcrurentSession()区别;
双向的关联关系;
一端可以看见多端对象
public class Clazz {// onetomany
private int cid;
private String cname;
// 关联属性集合
private Set<Student> stus;
public Clazz() {
// 初始化属性
stus = new HashSet<Student>();
}
//省略set,get方法
@Override
public String toString() {
return "Clazz [cid=" + cid + ", cname=" + cname + ", stus=]";
}
}
多端也可以一端的对象;
//一个班级有好多学生
public class Student {// manytoOne
private int sid;
private String sname;
private int age;
private double score;
// 关联属性
private Clazz clazz;
public Student() {
}
public Student(String sname, int age, double score) {
this.sname = sname;
this.age = age;
this.score = score;
}
//省略set,get方法
@Override
public String toString() {
return "Student [sid=" + sid + ", sname=" + sname + ", age=" + age + ", score=" + score + ", clazz=" + clazz
+ "]";
}
}
配置文件:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.baidu.bean">
<class name="Clazz" table="t_clazz">
<id name="cid" type="int">
<column name="cid" />
<generator class="native" />
</id>
<property name="cname" type="java.lang.String">
<column name="CNAME" />
</property>
<!--关联属性 -->
<set name="stus" table="t_student" inverse="false" cascade="save-update" lazy="false">
<key>
<column name="cid" />
</key>
<one-to-many class="Student" />
</set>
</class>
</hibernate-mapping>
<!--------------------------------------分割线------------------------------------------->
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.baidu.bean">
<class name="Student" table="t_student">
<id name="sid" type="int">
<column name="SID" />
<generator class="native" />
</id>
<property name="sname" type="java.lang.String">
<column name="SNAME" />
</property>
<property name="age" type="int">
<column name="AGE" />
</property>
<property name="score" type="double">
<column name="SCORE" />
</property>
<!-- 关联属性 -->
<many-to-one name="clazz" class="Clazz" fetch="join" lazy="false" cascade="save-update">
<column name="cid" />
</many-to-one>
</class>
</hibernate-mapping>
测试添加一个班级,班级里三个学生对象:
@Test
public void test00() {
//添加一个班级,里面有三个学生
Clazz clz=new Clazz();
clz.setCname("加强班");
Student s1=new Student("令狐冲",20,92);
Student s2=new Student("张无忌",21,82);
Student s3=new Student("刘德华",22,95);
clz.getStus().add(s1);
clz.getStus().add(s2);
clz.getStus().add(s3);
//添加一个班级,级联添加三个对象,班级来管理外键
//获取session
Session session = HbnUtil.getSession();
//开启事务
session.beginTransaction();
//执行添加操作
session.save(clz);
//提交事务
session.getTransaction().commit();
}
I.类级别:
<class>元素中lazy属性的可选值为true(延迟加载)和false(立即加载);
<class>元素中的lazy属性的默认值为true
II.一对多关联级别:
<set>元素中的lazy属性的可选值为:true(延迟加载),extra(增强延迟加载)和false(立即加载);
<set>元素中的lazy属性的默认值为true
III.多对一关联级别:
<many-to-one>元素中lazy属性的可选值为:proxy(延迟加载),no-proxy(无代理延迟加载)和false(立即加载)
<many-to-one>元素中的lazy属性的默认值为proxy