Hibernate的单向多对一映射

先要搞清楚什么是多对一。我们讲在班级-学生(高中时代,而不是大学时代)关系中,班级处于关系中one的位置,因为一个班级对应多个学生,所以学生处于many的位置。本篇文章也拿这个基本关系来做测试,看看在Hibernate中如何处理这种基本关系。

在此之前,我要声明一个事情,千万不要在数据库中使用SQL的关键字或者保留字。无论是什么数据库都最好不要这样做,因为它会给你带来无穷的麻烦,我亲身体会了实体名为order的痛苦。

好了,今天要操作的实体对象是grade(年级),属性包括int gid,String gname,String gdesc;

student(学生),属性包括int sid,String sname,String sex,Grade grade。

hbm.xml的配置文件不再说明。需要注意的是在单向多对一的关系中,需要在many的一端加上如下配置:

<many-to-one name="grade" class="edu.ctgu.hibernate.many2one.Grade">
            <column name="GID" />
</many-to-one>

 

 

 

这样在执行如下测试:

public class ManyToOneTest {
	private SessionFactory factory = null;
	private Session session = null;
	private Transaction transaction = null;
	@Before
	public void testBefore(){
		// 1.初始化配置文件加载配置信息,默认加载src目录下的hibernate.cfg.xml文件
		Configuration configuration = new Configuration().configure();
		// 2.初始化SessionFactory
		factory = configuration.buildSessionFactory();
		// 3.打开Session
		session = factory.openSession();
		// 4.开启事务
		transaction = session.beginTransaction();
	}
	
	@After
	public void testAfter(){
		transaction.commit();
		session.close();
		factory.close();
	}
	
	@Test
	public void test(){
	}
}

 

后Hibernate会新建两个表,并为student增加一个外键,具体打印的SQL语句如下:

Hibernate: 
    
    create table GRADE (
       GID integer not null auto_increment,
        GNAME varchar(255),
        GDESC varchar(255),
        primary key (GID)
    )
Hibernate: 
    
    create table STUDENT (
       SID integer not null auto_increment,
        SNAME varchar(255),
        SEX varchar(255),
        GID integer,
        primary key (SID)
    )
Hibernate: 
    
    alter table STUDENT 
       add constraint FKo3yntkpx77r18dsb45ak28no8 
       foreign key (GID) 
       references GRADE (GID)

 

好的,接下来讨论在Hibernate中增删查改需要注意的地方。

执行INSERT操作的save方法:

 

@Test
public void testSave(){
	Grade grade = new Grade("高三", "即将参加人生最重要考试的人");
	Student student = new Student("小明", "男");
	Student student2 = new Student("小红", "女");
		
	student.setGrade(grade);
	student2.setGrade(grade);
	// 方式一:先插入one的一端,在插入many的一端
	session.save(grade);
	session.save(student);
	session.save(student2);
	// 方式二:先插入many的一端,在插入one的一端
	/*session.save(student);
	session.save(student2);
	session.save(grade);*/
}

 

需要的注意的是在上面的方法中,方式一和方式二虽然处理完成的数据库结果是一样的,但是前者的效率比后者高。为什么呢?因为many存在外键关联one,可以说student依赖于grade。所以第一种方式只会产生三条insert语句。第二种方式则除了三条insert,还有两条update语句。

执行SELECT操作的get方法:

 

@Test
public void testGet(){
	Student student  = session.get(Student.class, 1);
	System.out.println(student.getSname());
	// 实际需要的时候才会执行对应的操作,得到的grade是代理对象
	System.out.println(student.getGrade());
	System.out.println(student.getGrade().getGdesc());
}

为了提高查询效率,Hibernate不会直接在查询many的时候将one一起查询出来,只有需要的时候才会再次执行一次查询语句。而且这里需要注意的是得到的grade不是实际的对象而是一个代理对象。这样的延迟加载也可能会出问题,如果中途Session被关闭,那么就无法查询到grade信息,出现懒加载异常。

执行UPDATE操作:

 

@Test
public void testUpdate(){
	Student student = session.get(Student.class, 1);
	student.setSname("小辉");
}

 

执行DELETE操作的delete方法:

@Test
public void testDelete(){
	Student student = session.get(Student.class, 1);
	session.delete(student);
}

这里需要注意的是在manyToOne的关系中,一般不可以直接删除one,也就是本例中的grade,因为它被依赖,所以无法直接删除,否则对应的操作会发生异常。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值