Hibernate 一对多双向映射及乐观锁使用

Hibernate 一对多双向映射及乐观锁使用
 
在“ Hibernate关联关系映射实例速查”一文中,通过myeclipse5.5,快速做出了Hibernate各种映射的示例。时隔快一年了,但是还是有博友向我索要工程源码,很遗憾的是已经找不到了。但找到一了一个测试代码:对双向关联和乐观锁的测试。其实映射类型很多,搞清楚一对多,基本上所有的映射就搞明白了,一对一也是一对多的特例而已,多对多也可以转换为一对多和多对一,并且实际中很少用到多对多。
 
还是老规矩,因为是测试,代码几乎全部是myeclipse生成的,我稍作了修改。并且应博友“阿飞”的留言,我做了详细的注释。
 
例子两部分:
1、一对多双向映射:模型是“班级-学生”模型。两个实体分别是Tclass和Student。
2、乐观锁的是使用,版本分别使用递增整数和时间戳。两个实体分别是Foo和Bar。
 
 
Tclass实体及其映射:
public class Tclass implements java.io.Serializable {

     // Fields

     private Long cid;

     private String cname;

     private Set students = new HashSet(0);

     // Constructors
     // Property accessors
    .......

     public String toString() {
         return "Tclass{" +
                 "cid=" + cid +
                 ", cname='" + cname + '\'' +
                '}';
    }
}
 
< hibernate-mapping >
     < class name ="stu.one2many.pojo.Tclass" table ="tclass" >
         < id name ="cid" type ="java.lang.Long" >
             < column name ="cid" />
             < generator class ="native" />
         </ id >
         < property name ="cname" type ="java.lang.String" >
             < column name ="cname" length ="24" not-null ="true" />
         </ property >
        <!-- set元素属性说明:
           name="students" 设置表示多个学生的变量名;
           inverse="true" 关系控制反转,不掌握主控权,表示Tclass不控制与Student关联关系,而是将这种关联控制的权利转给Student。
           cascade="all" 表示级联操作,操作班级的时候,对班级关联的学生也做同样的操作。
           lazy="true" 查询班级的时候,延迟查询班级下的学生。
        -->
         < set name ="students" inverse ="true" cascade ="all" lazy ="true" >
             < key >
                <!--
                    name="fk_cid" 指定关联的外键列;
                    not-null="true" 说明这个外间列不能为空,多余的。
                -->
                 < column name ="fk_cid" not-null ="true" />
             </ key >
            <!-- 指定所关联的类 -->
             < one-to-many class ="stu.one2many.pojo.Student" />
         </ set >
     </ class >
</ hibernate-mapping >
 
Student实体及其映射
public class Student implements java.io.Serializable {

     // Fields

     private Long sid;

     private Tclass tclass;

     private String sname;
  

     // Constructors
     // Property accessors
    .......

     public String toString() {
         return "Student{" +
                 "sid=" + sid +
                 ", sname='" + sname + '\'' +
                '}';
    }
}
 
< hibernate-mapping >
     < class name ="stu.one2many.pojo.Student" table ="student" >
         < id name ="sid" type ="java.lang.Long" >
             < column name ="sid" />
             < generator class ="native" />
         </ id >
        <!-- 表示多个Student关联一个Tclass -->
        <!--   
            name="tclass" 关联的成员变量名;
            class="stu.one2many.pojo.Tclass" 表示所关联的类;
            fetch="select" 查询策略,有两个选项select和join,
          select表示通过外联接来进行查询,查询速度稍慢,但消耗资源少;
          join表示通过内连接来查询,速度快,但消耗资源多.
         -->
         < many-to-one name ="tclass"  
             class ="stu.one2many.pojo.Tclass"  
             fetch ="select" >
            <!-- 指定关联的外键列 -->
             < column name ="fk_cid" not-null ="true" />
         </ many-to-one >
         < property name ="sname" type ="java.lang.String" >
             < column name ="sname" length ="24" not-null ="true" />
         </ property >
     </ class >
</ hibernate-mapping >
 
测试班级学生模型:
public class Test {

     /**
     * @param args
     */
     public static void main(String[] args) {
        testSave();
//        testDeleteTclass();

    }

     public static void testSave() {
        Tclass c = new Tclass();
        c.setCname( "某班级");
        Student s1 = new Student();
        Student s2 = new Student();
        s1.setSname( "张三");
        s1.setTclass(c);
        s2.setSname( "李四");
        s2.setTclass(c);
        c.getStudents().add(s1);
        c.getStudents().add(s2);

        Session session = HibernateSessionFactory.getSession();
        Transaction tx = session.beginTransaction();
        session.save(c);
        tx.commit();
        session.close();
    }

     public static void testUpdateClass() {
        System.out.println( "----------------正在调用testUpdateClass()----------------");
        Session session = HibernateSessionFactory.getSession();
        Tclass c = (Tclass) session.load(Tclass. class, Long.valueOf(1L));
        System.out.println(c);
        c.setCname( "班级更名");
        session.beginTransaction().commit();
    }

     public static void testUpdateStudent() {
        System.out.println( "----------------正在调用testUpdateStudent()----------------");
        Session session = HibernateSessionFactory.getSession();
        Tclass c = (Tclass) session.load(Tclass. class, Long.valueOf(3L));
        Student s = (Student) session.load(Student. class, Long.valueOf(2L));
        s.setSname( "学生改名换姓-王八");
        s.setTclass(c);
        System.out.println(c);
        System.out.println(s);
        session.beginTransaction().commit();
        System.out.println(s);
        System.out.println(s.getTclass());
    }

     public static void testDeleteStudent() {
        System.out.println( "----------------正在调用testDelete()----------------");
        Session session = HibernateSessionFactory.getSession();
        Student s = (Student) session.load(Student. class, Long.valueOf(5L));
        System.out.println(s);
        System.out.println(s.getTclass());
        session.delete(s);
        session.beginTransaction().commit();
    }

     public static void testDeleteTclass() {
        System.out.println( "----------------正在调用testDelete()----------------");
        Session session = HibernateSessionFactory.getSession();
        Tclass c = (Tclass) session.load(Tclass. class, Long.valueOf(3L));
        System.out.println(c);
        session.delete(c);
        session.beginTransaction().commit();
    }

     public static void testQueryClass() {
        System.out.println( "----------------正在调用testQueryClass()----------------");
        Session session = HibernateSessionFactory.getSession();
        Tclass c = (Tclass) session.load(Tclass. class, new Long( "1"));
        System.out.println(c);
        System.out.println(c.getStudents());

    }

     public static void testQueryStudent() {
        System.out.println( "----------------正在调用testQueryStudent()----------------");
        Session session = HibernateSessionFactory.getSession();
        Student s = (Student) session.load(Student. class, new Long( "1"));
        System.out.println(s);
        System.out.println(s.getTclass());
    }
}
 
 
下面是乐观锁的使用:
1、基于整数的版本控制
 
Foo实体和映射文件
public class Foo implements java.io.Serializable {

     // Fields

     private Long pid;

     private Integer version;

     private String name;

     // Constructors
     // Property accessors
    .......

     public String toString() {
         return "Foo{" +
                 "pid=" + pid +
                 ", version=" + version +
                 ", name='" + name + '\'' +
                '}';
    }
}
 
< hibernate-mapping >
     < class name ="stu.one2many.pojo.Foo" table ="foo"  
           optimistic-lock ="version" >
         < id name ="pid" type ="java.lang.Long" >
             < column name ="pid" />
             < generator class ="native" />
         </ id >
        <!-- 版本控制字段必须在id后配置 -->
         < version name ="version" type ="java.lang.Integer" >
             < column name ="version" />
         </ version >
         < property name ="name" type ="java.lang.String" >
             < column name ="name" length ="24" not-null ="true" />
         </ property >
     </ class >
</ hibernate-mapping >
 
测试:
public class TestFoo {

     /**
  * @param args
  */
     public static void main(String[] args) {
  testSave();
  
    }
     public static void testSave(){
  Foo foo1 = new Foo( "foo1");
  
  Session session = HibernateSessionFactory.getSession();
  session.save(foo1);
  session.beginTransaction().commit();
        session.close();
    }
}
 
2、基于时间戳的版本控制
public class Bar implements java.io.Serializable, Comparable {

     // Fields    

     private Long id;
     private Date timestamp;
     private String name;

     // Constructors
     // Property accessors
    .......

     public String toString() {
         return "Bar{" +
                 "id=" + id +
                 ", timestamp=" + timestamp +
                 ", name='" + name + '\'' +
                '}';
    }

     /**
     * 排序接口方法实现,为了能对查询结果按照id的大小进行排序
     * @param o 排序对象
     * @return 比较值
     */
     public int compareTo(Object o) {
        Bar bar = (Bar) o;
        Long res = this.id - bar.getId();
         return res.intValue();
    }
}
 
< hibernate-mapping >
     < class name ="stu.one2many.pojo.Bar" table ="bar" optimistic-lock ="version" >
         < id name ="id" type ="java.lang.Long" >
             < column name ="id" />
             < generator class ="native" />
         </ id >
         < version name ="timestamp" type ="java.util.Date" >
             < column name ="timestamp" length ="0" not-null ="true" />
         </ version >
         < property name ="name" type ="java.lang.String" >
             < column name ="name" length ="24" not-null ="true" />
         </ property >
     </ class >
</ hibernate-mapping >
 
public class TestBar {
     public static void main(String args[]) {
        testUpdateBar();
        testQueryBar();
    }

     public static void testSaveBar() {
        Bar bar = new Bar( "bar");
        Session session = HibernateSessionFactory.getSession();
        session.save(bar);
        session.beginTransaction().commit();
        session.close();
    }

     public static void testQueryBar() {
        Session session = HibernateSessionFactory.getSession();
        String hql = "from Bar";
        Query query = session.createQuery(hql);
        List<Bar> barList = query.list();
        Collections.sort(barList);
         for (Bar bar : barList) {
            System.out.println(bar.getId() + ":\t" + bar.getTimestamp().getTime());
        }
        session.close();
    }

     public static void testUpdateBar() {
        Session session = HibernateSessionFactory.getSession();
        String hql = "from Bar";
        Query query = session.createQuery(hql);
        List<Bar> barList = query.list();
         for (Bar bar : barList) {
            bar.setName( "newBar");
        }
        session.beginTransaction().commit();
        session.close();
    }
}
 
public class TestStack {
     public static void main(String args[]){
        test();
    }
     public static void  test(){
        Stack stack = new Stack();
        String s1= "1";
        String s2= "2";
        String s3= "3";
        String s4= "4";
        stack.push(s1);
        stack.push(s2);
        stack.push(s3);
        stack.push(s4);

         for(;!stack.isEmpty();){
            System.out.println(stack.pop());
        }

         //for语句先判断是否符合条件,然后确定是否执行循环
         for( int i=0;i>10;i--){
            System.out.println( ">>> "+i);
        }
    }
}
 
下面是SessionFactory工具和hibernate配置文件:
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;

/**
* Configures and provides access to Hibernate sessions, tied to the
* current thread of execution.  Follows the Thread Local Session
* pattern, see {@link [url]http://hibernate.org/42.html[/url] }.
*/
public class HibernateSessionFactory {

     /**  
     * Location of hibernate.cfg.xml file.
     * Location should be on the classpath as Hibernate uses  
     * #resourceAsStream style lookup for its configuration file.  
     * The default classpath location of the hibernate config file is  
     * in the default package. Use #setConfigFile() to update  
     * the location of the configuration file for the current session.    
     */
     private static String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml";
     private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
     private   static Configuration configuration = new Configuration();
     private static org.hibernate.SessionFactory sessionFactory;
     private static String configFile = CONFIG_FILE_LOCATION;

     static {
         try {
      configuration.configure(configFile);
      sessionFactory = configuration.buildSessionFactory();
  } catch (Exception e) {
      System.err
        .println( "%%%% Error Creating SessionFactory %%%%");
      e.printStackTrace();
  }
    }
     private HibernateSessionFactory() {
    }
  
     /**
     * Returns the ThreadLocal Session instance.  Lazy initialize
     * the <code>SessionFactory</code> if needed.
     *
     *  @return Session
     *  @throws HibernateException
     */
     public static Session getSession() throws HibernateException {
        Session session = (Session) threadLocal.get();

   if (session == null || !session.isOpen()) {
       if (sessionFactory == null) {
    rebuildSessionFactory();
      }
      session = (sessionFactory != null) ? sessionFactory.openSession()
        : null;
      threadLocal.set(session);
  }

         return session;
    }

     /**
     *  Rebuild hibernate session factory
     *
     */
     public static void rebuildSessionFactory() {
   try {
      configuration.configure(configFile);
      sessionFactory = configuration.buildSessionFactory();
  } catch (Exception e) {
      System.err
        .println( "%%%% Error Creating SessionFactory %%%%");
      e.printStackTrace();
  }
    }

     /**
     *  Close the single hibernate session instance.
     *
     *  @throws HibernateException
     */
     public static void closeSession() throws HibernateException {
        Session session = (Session) threadLocal.get();
        threadLocal.set( null);

         if (session != null) {
            session.close();
        }
    }

     /**
     *  return session factory
     *
     */
     public static org.hibernate.SessionFactory getSessionFactory() {
   return sessionFactory;
    }

     /**
     *  return session factory
     *
     *    session factory will be rebuilded in the next call
     */
     public static void setConfigFile(String configFile) {
  HibernateSessionFactory.configFile = configFile;
  sessionFactory = null;
    }

     /**
     *  return hibernate configuration
     *
     */
     public static Configuration getConfiguration() {
   return configuration;
    }

}

 
<? xml version ='1.0' encoding ='UTF-8' ?>
<!DOCTYPE hibernate-configuration PUBLIC
          "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<!-- Generated by MyEclipse Hibernate Tools.                   -->
< hibernate-configuration >

     < session-factory >
   < property name ="connection.username" >root </ property >
   < property name ="connection.url" >
      jdbc:mysql://localhost:3306/testdb
   </ property >
   < property name ="dialect" >
      org.hibernate.dialect.MySQLDialect
   </ property >
   < property name ="myeclipse.connection.profile" >
      com.mysql.jdbc.Driver
   </ property >
   < property name ="connection.password" >leizhimin </ property >
   < property name ="connection.driver_class" >
      com.mysql.jdbc.Driver
   </ property >
   < property name ="show_sql" >true </ property >
  <!-- <property name="format_sql">true</property>-->
         < property name ="hbm2ddl.auto" >create </ property >


         < mapping resource ="stu/one2many/pojo/Tclass.hbm.xml" />
   < mapping resource ="stu/one2many/pojo/Student.hbm.xml" />
   < mapping resource ="stu/one2many/pojo/Foo.hbm.xml" > </ mapping >
   < mapping resource ="stu/one2many/pojo/Bar.hbm.xml" />

     </ session-factory >

</ hibernate-configuration >
 
数据库用的是mysql5,sql脚本我导出了一份如下:
/*
SQLyog Enterprise - MySQL GUI v6.5
MySQL - 5.0.45-community-nt : Database - testdb
*********************************************************************
*/


/*!40101 SET NAMES utf8 */;

/*!40101 SET SQL_MODE=''*/;

/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;

create database if not exists testdb;

USE testdb;

/*Table structure for table bar */

DROP TABLE IF EXISTS bar;

CREATE TABLE bar (
  id bigint(20) NOT NULL auto_increment,
   timestamp datetime NOT NULL,
   name varchar(24) NOT NULL,
   PRIMARY KEY  (id)
) ENGINE=InnoDB DEFAULT CHARSET=gbk;

/*Table structure for table foo */

DROP TABLE IF EXISTS foo;

CREATE TABLE foo (
  pid bigint(20) NOT NULL auto_increment,
  version int(11) NOT NULL,
   name varchar(24) NOT NULL,
   PRIMARY KEY  (pid)
) ENGINE=InnoDB DEFAULT CHARSET=gbk;

/*Table structure for table student */

DROP TABLE IF EXISTS student;

CREATE TABLE student (
  sid bigint(20) NOT NULL auto_increment,
  fk_cid bigint(20) NOT NULL,
  sname varchar(24) NOT NULL,
   PRIMARY KEY  (sid),
   KEY FK8FFE823B3AA29689 (fk_cid),
   CONSTRAINT FK8FFE823B3AA29689 FOREIGN KEY (fk_cid) REFERENCES tclass (cid)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=gbk;

/*Table structure for table tclass */

DROP TABLE IF EXISTS tclass;

CREATE TABLE tclass (
  cid bigint(20) NOT NULL auto_increment,
  cname varchar(24) NOT NULL,
   PRIMARY KEY  (cid)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=gbk;

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
 
具体测试运行的结果运行下即可看到。
 
源码压缩包太大4M多,我删除了所有引用的包。使用的是hibernate3.1
 

本文出自 “熔 岩” 博客,转载请与作者联系!

你可能感兴趣的:(Hibernate,一对多,映射,乐观锁,休闲)