hibernate 的单独使用及关联研究
hibernate 的单独使用及关联研究。
目录结构

配置文件hibernate.cfg.xml
<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!--加载数据库驱动--> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="connection.url">jdbc:mysql://localhost:3306/hibernate1?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2b8</property> <property name="connection.username">root</property> <property name="connection.password">******</property> <!--指定数据库方言--> <property name="dialect">org.hibernate.dialect.MySQL5Dialect</property> <!-- DB schema will be updated if needed --> <property name="hibernate.hbm2ddl.auto">update</property> <!--在控制台显示SQL语句--> <property name="show_sql">true</property> <!--将SQL脚本中语句格式化在输出--> <property name="hibernate.format_sql">true</property> <!--事务的隔离级别 --> <property name="hibernate.connection.isolation">4</property> <!--配置session绑定当前线程--> <property name="current_session_context_class">thread</property> <!--罗列所有的持久化类--> <mapping resource="model/Classes.hbm.xml"/> <mapping resource="model/Studenr.hbm.xml"/> </session-factory> </hibernate-configuration>
Classes.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> <!--name:实体类名,table:对应数据库表名--> <class name="model.Classes" table="classes"> <!-- 配置主键映射 --> <!--name:实体类的属性名,column:数据库表的字段名,type:数据类型--> <id name="fdId" type="java.lang.String"> <column name="fd_id"></column> <!-- 设置主键生成方式 --> <generator class="uuid"></generator> </id> <!-- 配置其他属性 --> <!--name:实体类的属性名,column:数据库表的字段名,type:数据类型--> <property name="fdName" type="java.lang.String"> <column name="fd_name"></column> </property> <set name="studentList" inverse="true" cascade="all"> <key column="fd_classes_id"></key> <one-to-many class="model.Student"></one-to-many> </set> </class> </hibernate-mapping>
Studenr.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> <!--name:实体类名,table:对应数据库表名--> <class name="model.Student" table="student"> <!-- 配置主键映射 --> <!--name:实体类的属性名,column:数据库表的字段名,type:数据类型--> <id name="fdId" type="java.lang.String"> <column name="fd_id"></column> <!-- 设置主键生成方式 --> <generator class="uuid"></generator> </id> <!-- 配置其他属性 --> <!--name:实体类的属性名,column:数据库表的字段名,type:数据类型--> <property name="fdName" type="java.lang.String"> <column name="fd_name"></column> </property> <many-to-one column="fd_classes_id" name="classes" class="model.Classes" not-null="false"></many-to-one> </class> </hibernate-mapping>
一开始选择的主键生成策略都是native,不过保存的时候总会说没有默认的值什么的。搞得头疼,就换成了uuid
自动建表不知道怎么搞出来的,网上搜了一大堆,没什么用,可能是我的方式不对,手动用native加的表。
Classes
package model; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; public class Classes { private String fdId; private String fdName; private Set<Student> studentList = new HashSet<Student>(); public String getFdId() { return this.fdId; } public void setFdId(String fdId) { this.fdId = fdId; } public String getFdName() { return this.fdName; } public void setFdName(String fdName) { this.fdName = fdName; } public Set<Student> getStudentList() { return studentList; } public void setStudentList(Set<Student> studentList) { this.studentList = studentList; } @Override public String toString() { return "Classes{" + "fdId='" + fdId + '\'' + ", fdName='" + fdName + '\'' + ", studentList=" + studentList + '}'; } }
Student
package model; public class Student { private String fdId; private String fdName; private Classes classes; public String getFdId() { return fdId; } public void setFdId(String fdId) { this.fdId = fdId; } public String getFdName() { return fdName; } public void setFdName(String fdName) { this.fdName = fdName; } public Classes getClasses() { return classes; } public void setClasses(Classes classes) { this.classes = classes; } @Override public String toString() { return "Student{" + "fdId='" + fdId + '\'' + ", fdName='" + fdName + '\'' + ", classes=" + classes + '}'; } }
工具类HibernateUtil
package utils; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; public class HibernateUtil { private static Configuration cfg = new Configuration().configure(); private static SessionFactory sessionFactory; public static Session getSession(){ Session session = getSessionFactory().openSession(); return session; } private static SessionFactory getSessionFactory(){ if(sessionFactory==null){ setSessionFactiory(); } return sessionFactory; } private static void setSessionFactiory() { sessionFactory = cfg.buildSessionFactory(); } public static Session getCurrentSession(){ return getSessionFactory().getCurrentSession(); } }
当设置成 inverse=“true" cascade="all"的时候。测试代码如下
Session session = HibernateUtil.getCurrentSession(); Transaction tx = session.beginTransaction(); Classes classes = new Classes(); classes.setFdName("aa啊啊"); //session.save(classes); System.out.println(classes.getFdName()); Student student = new Student(); student.setFdName("qwea网啊水水"); student.setClasses(classes); session.save(student); tx.commit();
此时保存失败,classes是瞬时态
但如果把session.save(classes)这句加上就没问题了
当然了,在student的hbm配置文件里面加上级联关系就可以了,一般也应该是这样做的。
两张表都设置cascade=all,classes设置inverse=true
Session session = HibernateUtil.getCurrentSession(); Transaction tx = session.beginTransaction(); Classes classes = new Classes(); classes.setFdName("aa啊w啊"); System.out.println(classes.getFdName()); Student student = new Student(); student.setFdName("qwea网啊水w水"); classes.getStudentList().add(student); session.save(classes); tx.commit();
此时由于外键交由student维护,所以,保存classes的时候外键并不会保存,但子表student是会保存的,只是没有外键。
如果在保存这群给student添加classes
student.setClasses(classes);
那么就可以保存外键了,因为student维护外键,所以会保存。
当然,如果不添加这句代码,将配置文件的inverse=true改为false,那么不要给student set一个classes,保存classes的时候也会保存外键。
研究这些问题,主要是查资料的时候看见网上一些人讨论inverse和cascade的关系,总感觉有的说法很矛盾,自己没有深入研究过,现在简单的研究一下。
inverse和cascade并没有什么绝对的关系,inverse只是影响外键的维护,cascade影响从表是否跟随主表保存或者删除。但它们肯定是相互影响的.
举例来说:
当设置classes inverse=true,cascade=true;student cascade=all。这时候执行cleasess.getFdStudentList().clear();save(cleases);
这个时候是不会其效用的,因为classes并不维护外键。只有是设置inverse=false的时候才会将外键置为空。额外的,此时设置classes inverse=false,cascade=all-delete-orphand的时候。
就会直接删除student了。

两者相互作用决定了最后数据库怎么保存的。
浙公网安备 33010602011771号