hibernate小结

映射:

单向多对一就是在多的里面设一个一的对象;

单向一对多就是在一的里面设一个多的集合(注意此时多的里面要有一个与外键有关的属性);

单向关系都非常简单,这里只贴出双向一对多的代码(将单向一对多和单向多对一合并所得)

District.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 package="model">
  <class name="District" table="district">
     <id name="id">
        <column name="id"></column>
        <generator class="increment"></generator>
     </id>
     <property name="name"></property>
     <set name="streets" table="street" inverse="true" cascade="all">
       <key column="district"></key>
       <one-to-many class="Street"/>
     </set>
  </class>
</hibernate-mapping>


 

Street.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 package="model">
   <class name="Street" table="street">
      
      <id name="id">
         <column name="id"></column>
         <generator class="increment"></generator>
      </id>
      <property name="name"></property>
      <many-to-one name="district">
         <column name="district"></column>
      </many-to-one>
      
   </class>
</hibernate-mapping>


 

District.java

 

        private int id;
	private String name;
	private Set<Street> streets=new HashSet<Street>();

Street.java

        private int id;
	private String name;
	private District district;

Test.java

public static void main(String[] args) {
		Configuration cfg=new Configuration().configure();
		SessionFactory sf=cfg.buildSessionFactory();
		Session session=sf.openSession();
		Transaction tr=null;
		try{
			//最佳实践:最好要先设置一的一方,让多的一方来找多的一方
			tr=session.beginTransaction();
			District d1=new District();
			
			d1.setName("海淀区");
			
			Street s1=new Street();
			
			s1.setName("北洼路");
			d1.getStreets().add(s1);
			s1.setDistrict(d1);
			//session.save(s1);
			Street s2=new Street();
			
			s2.setName("闽南路");
			d1.getStreets().add(s2);
			s2.setDistrict(d1);
			
			//当一的一方set中的inverse="true"时,多的一方要手动如下代码设置关联
			//这样少了一句Update语句,提高了一些效率
			//d1.getStreets().add(s2);
			//s2.setDistrict(d1);
			
			//session.save(s2);
			//使用级联cascade="all" 对d1的操作会自动关联到与它有关的对象
			session.save(d1);
			session.delete(d1);
			
			tr.commit();
		}catch(HibernateException e){
		    tr.rollback();
			e.printStackTrace();
		    
		}finally{
			session.close();
		}

	}


 

ps:cascade和inverse属性一般都设在set(即一的一方)比较好。 cascade可以级联操作,如果保存了district,则与其相关的street的也会保存。

       inverse是控制反转,inverse="false"为主动方,将<set>中inverse设为true,则不会自动更新外键值,由多的一方去找一的一方,效率更高。(多个学生找一个老师比一个老师找多个学生效率高)。所以要手动关联d1.getStreets().add(s1);s1.setDistrict(d1);  

 

双向多对多
使用Many2Many不论在哪一方来维护关系都比较的麻烦,而且很多时候关联表中需要加入其他的属性
 所以在开发中,经常使用两个一对多来替代多对多

示例如下:

Couse.java

        private int id;
	private String name;
	private Set<TeacherCourse> tcs;

Teacher.java

        private int id;
	private String name;
	private Set<TeacherCourse> tcs;


CouseTeacher.java

        private int id;
	private double ach;
	private Teacher teacher;
	private Course course;

Couse.xml

<class name="Course" table="t_course">
        <id name="id">
          	<generator class="native"/>
        </id>
        <property name="name"/>
        <set name="tcs" lazy="extra" inverse="true">
        	<key column="cid"/>
        	<one-to-many class="TeacherCourse"/>
        </set>
</class>

Teacher.xml

<class name="Teacher" table="t_teacher">
        <id name="id">
          	<generator class="native"/>
        </id>
        <property name="name"/>
        <set name="tcs" lazy="extra" inverse="true">
        	<key column="tid"/>
        	<one-to-many class="TeacherCourse"/>
        </set>
</class>


CourseTeacher.xml




 <class name="TeacherCourse" table="t_teacher_course">
        <id name="id">
          	<generator class="native"/>
        </id>
        <property name="ach"/>
        <many-to-one name="teacher" column="tid"/>
        <many-to-one name="course" column="cid"/>
 </class>


 Test.java

@Test
	public void testAdd01() {
		Session session = null;
		try {
			session = HibernateSessionFactory.getSession();
			session.beginTransaction();
			Teacher t1 = new Teacher();
			t1.setName("老张");
			session.save(t1);
			Teacher t2 = new Teacher();
			t2.setName("老刘");
			session.save(t2);
			Course c1 = new Course();
			c1.setName("数据结构");
			session.save(c1);
			Course c2 = new Course();
			c2.setName("计算机组成原理");
			session.save(c2);
			TeacherCourse tc1 = new TeacherCourse();
			tc1.setAch(87);
			tc1.setTeacher(t1);
			tc1.setCourse(c1);
			session.save(tc1);
			
			tc1 = new TeacherCourse();
			tc1.setAch(66);
			tc1.setTeacher(t1);
			tc1.setCourse(c2);
			session.save(tc1);
			
			tc1 = new TeacherCourse();
			tc1.setAch(190);
			tc1.setTeacher(t2);
			tc1.setCourse(c1);
			session.save(tc1);
			
			tc1 = new TeacherCourse();
			tc1.setAch(20);
			tc1.setTeacher(t2);
			tc1.setCourse(c2);
			session.save(tc1);
			session.getTransaction().commit();
		} catch (Exception e) {
			e.printStackTrace();
			if(session!=null) session.getTransaction().rollback();
		} finally {
			HibernateSessionFactory.closeSession();
		}
	}
	
	@Test
	public void testLoad01() {
		Session session = null;
		try {
			session = HibernateSessionFactory.getSession();
			session.beginTransaction();
			Teacher t = (Teacher)session.load(Teacher.class, 1);
			//load的时候由于延迟加载,会根据不同的情况取相应的关联对象,所以会发出大量的sql
			/**
			 * 总体来说:最佳实践就是,尽量不使用双向关联,特别不建议使用一的这一方的关联
			 * 因为从一的这一端取关联对象很有可能会涉及到分页操作,所以基本不会使用
			 * 在设计的时不是特殊情况不要使用双向关联
			 */
			System.out.println(t.getName());
			for(TeacherCourse tc:t.getTcs()) {
				System.out.println(tc.getCourse().getName()+":"+tc.getAch());
			}
			session.getTransaction().commit();
		} catch (Exception e) {
			e.printStackTrace();
			if(session!=null) session.getTransaction().rollback();
		} finally {
			HibernateSessionFactory.closeSession();
		}
	}


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值