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,因爲它被依賴,所以無法直接刪除,否則對應的操作會發生異常。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章