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&amp;characterEncoding=UTF-8&amp;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了。

 

 

 两者相互作用决定了最后数据库怎么保存的。

 

 


posted @ 2020-06-10 13:27  憨安憨  阅读(233)  评论(0)    收藏  举报