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 http://hibernate.org/42.html }. */ 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
本文出自 “熔 岩” 博客,转载请与作者联系! 本文出自 51CTO.COM技术博客 |
附件下载:
工程源码
工程源码


leizhimin
博客统计信息
热门文章
最新评论
友情链接