hibernate中ManyToOne单向

2019-03-28 15:09|来源: 领悟书生

开始hibernate的关系映射,先来个多对一单向关系映射。例子是班级和学生之间的关系。


班级的实体和映射

Classroom.java

package org.zttc.itat.model;
 
import java.util.Set;
 
public class Classroom {
    private int id;
    private String name;
    private int grade;
    //set get 方法省去
}

Classroom.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="org.zttc.itat.model">
    <class name="Classroom" table="t_cla">
        <id name="id">
            <generator class="native"/>
        </id>
        <property name="name"/>
        <property name="grade"/>
    </class>
</hibernate-mapping>


学生的实体和映射

Student.java

package org.zttc.itat.model;
 
public class Student {
    private int id;
    private String name;
    private String no;
    private Classroom classroom;
    //set get 方法省去
}

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="org.zttc.itat.model">
    <class name="Student" table="t_stu">
        <id name="id">
            <generator class="native"/>
        </id>
        <property name="name"/>
        <property name="no"/>
        <!-- many-to-one用来映射多对一,name表示对象中的属性名称 ,
        column用来表示外键的名称-->
        <many-to-one name="classroom" column="cid"/>
    </class>
</hibernate-mapping>


测试方法:

public class TestManyToOne {
    @Test
    public void testAdd01() {
    Session session = null;
        try {
        session = HibernateUtil.openSession();
        session.beginTransaction();
        //先添加1
        Classroom c = new Classroom();
        c.setGrade(2012);
        c.setName("计算机网络技术");
        session.save(c);
        Student stu1 = new Student();
        stu1.setName("猪八戒");
        stu1.setNo("001");
        stu1.setClassroom(c);
        session.save(stu1);
        Student stu2 = new Student();
        stu2.setName("孙悟空");
        stu2.setNo("002");
        stu2.setClassroom(c);
        session.save(stu2);
     
        session.getTransaction().commit();
    } catch (Exception e) {
        e.printStackTrace();
        if(session!=null) session.getTransaction().rollback();
    } finally {
        HibernateUtil.close(session);
    }
    }
     
    @Test
    public void testAdd02() {
    Session session = null;
    try {
            session = HibernateUtil.openSession();
        session.beginTransaction();
        //先添加多
        Student stu1 = new Student();
        stu1.setName("沙僧");
        stu1.setNo("003");
        session.save(stu1);
        Student stu2 = new Student();
        stu2.setName("唐僧");
        stu2.setNo("004");
        session.save(stu2);
        Classroom c = new Classroom();
        c.setGrade(2012);
        c.setName("计算机应用技术");
        session.save(c);
        //此时还会发两条update
        stu1.setClassroom(c);
        stu2.setClassroom(c);
        //最佳实践:一定要先添加一的一方,之后在添加多的一方
        session.getTransaction().commit();
    } catch (Exception e) {
        e.printStackTrace();
        if(session!=null) session.getTransaction().rollback();
    } finally {
        HibernateUtil.close(session);
    }
    }
     
    @Test
    public void testLoad() {
    Session session = null;
    try {
            session = HibernateUtil.openSession();
        session.beginTransaction();
        Student stu = (Student)session.load(Student.class, 1);
        //此时仅仅只是发一条sql
        System.out.println(stu.getName());
        //此时student的关联对象Classroom也是延迟加载的,会再发一条sql来取对象
        System.out.println(stu.getClassroom().getName());
            session.getTransaction().commit();
    } catch (Exception e) {
        e.printStackTrace();
        if(session!=null) session.getTransaction().rollback();
    } finally {
        HibernateUtil.close(session);
    }
    }
}


如果在添加student的时候,Classroom还没保存,就会出现抛异常如:

@Test
public void testAdd03() {
    Session session = null;
    try {
        session = HibernateUtil.openSession();
        session.beginTransaction();
        Classroom c = new Classroom();
        c.setGrade(2012);
        c.setName("计算机信息管理");
        //此时classroom没有存储,所以在添加student的时候没有外键,会抛出异常
        Student stu1 = new Student();
        stu1.setName("如来");
        stu1.setNo("005");
        session.save(stu1);
        Student stu2 = new Student();
        stu2.setName("观音");
        stu2.setNo("006");
        session.save(stu2);
        stu1.setClassroom(c);
        stu2.setClassroom(c);
        session.getTransaction().commit();
    } catch (Exception e) {
        e.printStackTrace();
        if(session!=null) session.getTransaction().rollback();
    } finally {
        HibernateUtil.close(session);
    }
}

这时我们可以添加级联(级联是指两个对象之间的操作联动关系,对一个对象执行了操作之后,对其指定的级联对象也需要执行相同的操作)

修改Student.hbm.xml,在many-to-one加cascade属性

<!-- 当设置了cascade的时候,会自动完成关联,如果添加时没有关联对象,会自动创建一个关联对象
    最佳实践:如果没有特殊情况不要使用cascade,特别注意,可能使用cascade的地方一般都是一的一方进行删除时使用,特殊需求才会使用cascade的add,正常情况add方法都是应该有程序员完成添加 -->
<many-to-one name="classroom" column="cid" cascade="add"/>

可能使用cascade的地方一般都是一的一方进行删除时使用这句话解释一下,如果在多的一方设置级联删除,例如删除一个学生,也把一个班级给删了,但这个班级可能还有其他学生,所以删除的时候会出异常。所以如果要用,就用在一的一方。

一般对<many-to-one>或<many-to-many>关联关系不设置级联(Cascade)操作


本文链接:hibernate中ManyToOne单向,由领悟书生原创(笔记),转载请注明出处http://www.656463.com/article/397

相关问答

更多
  • 有什么问题是以下几点: @OneToMany(fetch = FetchType.LAZY) @JoinColumn(name="idEmployees") public List getTasks() { return tasks; } 这有两个原因是错误的。 @JoinColumn(name="idEmployees")表示:使用名为idEmployees的连接列(即外键)映射此OneToMany。 但连接列未命名为idEmployees。 idEmployees是Employee ...
  • 尝试从过滤器定义中删除stock @Filter(name="stockDailyRecordFilter", condition="name = 'My stock'") 更新因此这里的股票是相关表而不是主表。 您可以尝试加入以使用IN进行子选择 condition="stock_id in (select id from stock where name = 'My stock')" Try to remove the stock from filter definition @Filter(nam ...
  • 我将这个答案更好地解释,但请记住,这些都是hibernate映射的基础,你可以在任何在线教程中阅读它们。 用户表格是: userId userName etc 和车辆表 vehicleId userIdFK etc 它是一个显而易见的很多关系:一个用户更多的车辆。 为了映射这种关系,你有 @Entity class User { @Id private userId; private String userName // other code } 和 ...
  • 是的,也可以为ManyToOne关系编制索引。 在大多数简单的情况下,你有一个实体,如Club标记为@Indexed ,然后你想索引它的一些字段,并通过相关实体Player @IndexedEmbedded属性嵌入 。 到目前为止,你做对了,这基本上为你的club指数定义了“扁平化”的架构。 问题是,在为player索引定义架构时,您将firstname标记为索引字段,但没有指示它将关系嵌入到playersClub 。 基本上你在这个属性上缺少@IndexedEmbedded 。 不要与@Contained ...
  • 对于任何有类似问题的人,我通过改变解决了这个问题 /** * User who logged the work * * @ORM\ManyToMany(targetEntity="Application\Apps\Timesheet\Entity\User",cascade={"persist", "remove"}) * @ORM\JoinTable(name="timesheet_worklog_user", * joinColumns={@ORM\JoinColumn(name=" ...
  • 如果关联是ManyToOne,则没有理由使用OneToOne,反之亦然。 使用适当的注释,它反映了关联的基数的真实性。 不这样做只会混淆应用程序的开发人员,如果不是Hibernate本身。 在数据库中,源的唯一性是否受限制并不会改变Hibernate的任何内容。 根据我的经验,Hibernate 确实在OneToOne的情况下创建了唯一的约束,如果没有,那么您应该创建它(我不会使用Hibernate创建模式,除非是快速的n肮脏的演示应用程序)。 但是,当然,如果存在唯一约束,并且您尝试使用相同的目标实体创建 ...
  • JPA规范(11.1.17) - EmbeddedId注释 EmbeddedId注释应用于实体类或映射超类的持久字段或属性,以表示一个可嵌入类的组合主键。 可嵌入类必须标注为Embeddable。[104] 不支持在嵌入式id类中定义的关系映射。 JPA规范(2.11.2) - 映射超类 被指定为映射超类的类可以以与实体相同的方式进行映射, 只不过映射将仅应用于其子类,因为映射超类本身不存在表 。 您不能在@Embeddable中将关系映射用作@EmbeddedId。 即使你在@MappedSuper类中有 ...
  • 这个人可以拥有联盟或联盟的任务,这意味着任何时候任何一个人都将是空的。 因此,加入列上的可空值是真实的。 因此,你没有获得任务数据。 当您使用延迟加载时,单独针对特定任务的单独查询将被触发而无需加入联合表,当您调用person对象上的getMandates()时将返回结果。 The person can have mandate for either league or federation which means either one of them will be null at any point o ...
  • 请找到下面的课程。 主要更改: http : //docs.oracle.com/javaee/6/api/javax/persistence/JoinColumn.html#nullable()指定以下行: nullable = false @JoinColumn(name = "deptno", referencedColumnName = "deptno", nullable = false) 这使得deptNo列不为null。 另外指定deptNo为非空列,所以它避免了不用dept数而保存empd ...
  • 这一切都取决于你对这些实体的用途,但我认为如果文章知道哪些评论与其自身相关联而不是相反,那么它会更有用。 这样,您可以轻松地操作文章注释而无需使用存储库,或在树枝模板等中... 因为我不是真的很喜欢使用第三个表(使用OneToMany单向映射),其中实体两个表完成工作,我建议使用双向映射。 It all depends on the use you will have of those entities, but I think it's more useful if the article knows w ...