hibernate--单向一对多

Posted 独白

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hibernate--单向一对多相关的知识,希望对你有一定的参考价值。

一.概述

单向一对多,双向多对多我就不写了,网上好多。一对多,多对一都是为了表级完整性,防止数据冗余,无意义数据记录的产生。作用其实就是相当于前台的表单验证,你输了一个密码,这个密码在表里不存在,会出错。

一对多和多对一都是在多那一段的表建立外键关联,就是去维护数据方不同。

单向一对多:当一这一端的对象需要用到多这一端的对象。比如班级类对象,一个班级有很多学生,我想在加载班级的时候顺便加载所有的学生,显示他们的名字,这样的话我们就要在班级对象里存放一个集合属性,用来存放相关班级的所有学生了。

我这里用的是list,对应你实际的例子用对应的最好的东西,list是有序可以重复,set是无序不可以重复,因为不能重复所以往往用set

二.代码

1.单向一对多。

①class.java--班级类,代表一这端

package com.st.test;

import java.util.ArrayList;
import java.util.List;

public class Class {
    private int id;//自增主键
    private String className;//班级名
    private List<Student> students=new ArrayList<Student>();//一对多中用到的多一端的对象
    
    //对应getter,setter
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getClassName() {
        return className;
    }
    public void setClassName(String className) {
        this.className = className;
    }
    public List<Student> getStudents() {
        return students;
    }
    public void setStudents(List<Student> students) {
        System.out.println(students.size());
        for(Student s:students){
            System.out.println("设置studnets+"+s.getStudentname());
        }
        this.students = students;
    }
    
    
}

②student.java

package com.st.test;

public class Student {
    private int id;//主键
    private String studentname;//学生名
    
    //对应gettter,setter
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getStudentname() {
        return studentname;
    }
    public void setStudentname(String studentname) {
        this.studentname = studentname;
    }
}

③Class.hbm.xml--关键的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">
<!-- Generated 2017-4-24 15:36:01 by Hibernate Tools 3.5.0.Final -->

<hibernate-mapping>
    <!-- 下面就是这个class对应的配置 -->
    <class name="com.st.test.Class" table="CLASS">
        <!-- 下面这个节点是配置主键 -->
        <id name="id" type="int">
            <column name="ID" />
            <generator class="identity" />
        </id>
           <!-- 普通的属性配置 -->
        <property name="className" type="java.lang.String">
            <column name="CLASSNAME" />
        </property>
        <!-- 下面是个重要的点:key里的column表示你想在student表里作为外键关联的那列的列名,别用自动生成的’ID‘这个名字,会和student的自增主键id冲突 -->
        <list name="students" inverse="false" table="STUDENT" lazy="true">
            <key>
                <column name="class_id" />
            </key>
            <!-- 这个是用list做集合时会有的,它会在表后面再加一列idx,作为元素在list里的位子。 -->
            <list-index></list-index>
            <one-to-many class="com.st.test.Student" />
        </list>
    </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">
<!-- Generated 2017-4-24 13:55:39 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
    <class name="com.st.test.Student" table="STUDENT">
        <id name="id" type="int">
            <column name="ID" />
            <generator class="identity" />
        </id>
        <property name="studentname" type="java.lang.String">
            <column name="STUDENTNAME" />
        </property>
    </class>
</hibernate-mapping>

⑤测试代码

package com.st.test;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.springframework.transaction.annotation.Transactional;


@Transactional
public class Test {
    
    public static void main(String[] args) {
        
        Configuration cfg = new Configuration();
        cfg.configure();//此处不指定,会默认读取src根目录下名为hibernate.cfg.xml的文件。也可以指定如:cfg.configure(“hibernate.xml”);
        SessionFactory sessionfactory = cfg.buildSessionFactory();
        Session session=sessionfactory.openSession();
        
        session.beginTransaction();//事务开始
        
        //先声明要用到的多的一端的对象,并且保存,不保存,这个对象还是游离对象
        Student s1=new Student();
        s1.setStudentname("student1");
        
        
        Student s2=new Student();
        s2.setStudentname("student2");
        
        session.save(s1);
        session.save(s2);
        //student对象声明结束
        
        //list是因为我们要设置这个班级的属性student学生集合时用的
        List<Student> list=new ArrayList<Student>();
        list.add(s1);
        list.add(s2);
        
        //声明一端对象class,并且保存到数据库
        Class c=new Class();
        c.setClassName("class1");
        c.setStudents(list);
        session.save(c);
        
        session.getTransaction().commit();//事务提交,这之后数据库就会改变
    }
}

⑥sql语句

Hibernate: 
    insert 
    into
        STUDENT
        (STUDENTNAME) 
    values
        (?)
Hibernate: 
    insert 
    into
        STUDENT
        (STUDENTNAME) 
    values
        (?)
Hibernate: 
    insert 
    into
        CLASS
        (CLASSNAME) 
    values
        (?)
Hibernate: 
    update
        STUDENT 
    set
        class_id=?,
        idx=? 
    where
        ID=?
Hibernate: 
    update
        STUDENT 
    set
        class_id=?,
        idx=? 
    where
        ID=?

*从这里我们也可以看出,由一这一端去维护后面要多用update语句去更新对应的student的外键关联列,这里还好只是2个对象,要是多了,这update语句就可怕了。所以多对一比一对多要好一些的。

*还有就是,在student表的那个外键class_id不可以设置为not null,因为设置了非空约束的话,一开始的保存student对象就会出错,因为你保存student时是暂时没有设置外键关联的那个class的id值的

三.总结

这是我在测试hibernate,单向一对多,单向多对一,双向多对多过程中,单向一对多是唯一不小心出错的,简单记录下,这个东西网上有很多的参考。前辈们路过,有错的地方请指正,谢谢大家。

qq:2656062151  email:[email protected] (非问问题勿扰)

 

以上是关于hibernate--单向一对多的主要内容,如果未能解决你的问题,请参考以下文章

hibernate--单向一对多

映射一对多-01单向cascadelazy

一口一口吃掉Hibernate——一对多单向关联映射

Hibernate中的多表操作:单向一对多

hibernate单向一对多级联操作

hibernate 一对多单向xml配置方式