为了账号安全,请及时绑定邮箱和手机立即绑定

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

标签:
MySQL


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

 

附件:http://down.51cto.com/data/2349994

©著作权归作者所有:来自51CTO博客作者leizhimin的原创作品,如需转载,请与作者联系,否则将追究法律责任

映射Hibernate休闲ORM/持久化


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消