`
anxin587
  • 浏览: 23409 次
最近访客 更多访客>>
社区版块
存档分类
最新评论

hibernate初级 映射对象标识符

阅读更多

Hibernate使用对象标识符来建立内存中的对象和数据库表中记录的对应关系,我们多知道关系数据库用主键来标识并记录每条记录的唯一性,我们把具有业务含义的字段作为主键称为自然主键,而不具备业务含义的字段称为代理主键,比较两变量所引用的内存地址是否相等用==,equals是按照内存地址来比较的。

Hibernate用对象标识符来区分对象,

 public static void testEquals()
 {
  Session session=HibernateUtil.getSessionFactory().openSession();
  Customer c1=(Customer)session.load(Customer.class,new Long(1));
  Customer c2=(Customer)session.load(Customer.class,new Long(1));
  Customer c3=(Customer)session.load(Customer.class,new Long(2));
  System.out.println(c1==c2);
  System.out.println(c1==c3);
  session.getTransaction().commit();

 }上面的方法中c1==c2 输出true,第2个输出false,第一个自因为会是true,是因为第一次加载OID为1的Customer对象再数据库表中查处id为1 的记录,从而创建Customer的实例,并且把他保存到了Session缓存中,最后赋给c1,这样当第2次load OID为1的对象的时候直接从缓存中取得Customer对象把引用赋给c2,所以c1==c2。

Hibernate允许在持久化类把OID定义为short (Short)2字节,int(Integer)4字节,long(Long)8字节,在对象关系映射中<id></id>元素用来设置对象标识符

<id column="ID" type="long" name="id"></id>

    <generator class="increment"></generator><!---->

 

increment 标识符生成器有Hibernate以递增方式为代理主键赋值,hibernate在初始化阶段读取表中的最大主键值,由此可见increment标识符生成器仅仅在只有单个hibernate应用进程访问数据库的情况下才能有效工作,即使在同一个进程中创建了链接同一个数据库的多个SessionFactory实例,也会导致插入duplicate,但是他不依赖底层数据库系统,因此他适合与所有数据库系统,在集群环境下不推荐使用,Oid必须为long int short

identity由底层数据库来负责生成标识符,他要求把底层主键定义为自动增长字段类型,所以他要求底层数据库必须支持自动增加字段类型,

sequence标识符生成器利用底层数据库提供的序列来生成标识符,要求底层数据库支持序列

hilo 由Hibernate按照一种high/low算法来生成标识符

<id column="ID" type="long" name="id"></id>

<generator class="hilo"></generator>

hi_value

next_value

100

 

 

create table Hilo_TESTER( ID BIGINT NOT NULL, NAME VARCHAR(15),PRIMARY KEY (ID));

CREATE TABLE HI_VALUE(NEXT_VALUE INTEGER);

native 标识符生成器,依据底层数据库对自动生成标识符的支持能力来选择identity,sequence或者hilo标识符

映射自然主键

<id column="NAME" type="string" name="name"></id>

<generator class="assigned"></generator>

 

<version column="VERSION" name="version" unsaved-value="0"></version>

这样由应用程序为name属性赋值,不管对象是游离的还是持久的,name属性不会为null通过设置version属性的unsaved-value属性来判断,如果version属性为0表示临时对象,否则为游离对象,

映射复合自然主键有两种方式,下面将分别介绍

例子如下


CREATE TABLE HIB5_2
(
 ID2 INT,
 NAME VARCHAR(20),
 AGE INT,
 PRIMARY KEY(ID2,NAME)
)

这张表具有复合主键,映射方式一

 

package entity;
public class Hib5_2 implements java.io.Serializable
{
 private Long id2;
 private String name;
 private int age;

 public void setId2(Long id2)
 {
  this.id2=id2;
 }
 public Long getId2()
 {
  return this.id2;
 }

 public void setName(String name)
 {
  this.name=name;
 }
 public String getName()
 {
  return this.name;
 }

 public void setAge(int age)
 {
  this.age=age;
 }
 public int getAge()
 {
  return this.age;
 }
}

 上面是java文件

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="entity">
 <class name="Hib5_2" table="HIB5_2">
  <composite-id>
   <key-property name="id2" type="long" column="ID2"/>
   <key-property name="name" type="string" column="NAME"/>
  </composite-id>
  <!--<version name="version" column="VERSION" unsaved-value="null"/>-->
  <property name="age" type="int" column="AGE"/>
 </class>
</hibernate-mapping>

映射文件如上所示

public static void testHib5_2()
 {
  /*
  Session session=HibernateUtil.getSessionFactory().openSession();
  session.beginTransaction();
  Hib5_2  hib=new Hib5_2();
  hib.setId2(new Long(1));
  hib.setName("andy");
  hib.setAge(24);
  session.save(hib);
  session.getTransaction().commit();
  //*/
 }
test方法如上面,这样就把数据保存到数据库中

第2中方式是定义单独的主键类

package entity;
import java.io.Serializable;
// define a sigle key class
public class Hib_id implements Serializable
{
 private Long id2;
 private String name;

 public Hib_id(Long id2,String name)
 {
  this.id2=id2;
  this.name=name;
 }

 public void setId2(Long id2)
 {
  this.id2=id2;
 }
 public Long getId2()
 {
  return this.id2;
 }

 public void setName(String name)
 {
  this.name=name;
 }
 public String getName()
 {
  return this.name;
 }
}

如上面所示,这个是单独的主键类

package entity;
public class Hib5_2 implements java.io.Serializable
{
 private Hib_id id;
 private int age;

 public void setId(Hib_id id)
 {
  this.id=id;
 }

 public Hib_id getId()
 {
  return this.id;
 }

 public void setAge(int age)
 {
  this.age=age;
 }
 public int getAge()
 {
  return this.age;
 }
}

映射类如上面所示

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="entity">
 <class name="Hib5_2" table="HIB5_2">
  <!--
  <composite-id>
   <key-property name="id2" type="long" column="ID2"/>
   <key-property name="name" type="string" column="NAME"/>
  </composite-id>
  -->
  <composite-id name="id" class="Hib_id">
   <key-property name="id2" type="long" column="ID2"/>
   <key-property name="name" type="string" column="NAME"/>
  </composite-id>
  <!--<version name="version" column="VERSION" unsaved-value="null"/>-->
  <property name="age" type="int" column="AGE"/>
 </class>
</hibernate-mapping>

映射文件如上所示

public static void testHib5()
 {
  Session session=HibernateUtil.getSessionFactory().openSession();
  session.beginTransaction();
  Hib_id hi=new Hib_id(new Long(2),"andy2");
  Hib5_2 hib2=new Hib5_2();
  hib2.setId(hi);
  hib2.setAge(24);
  session.save(hib2);
  session.getTransaction().commit();
 
 }

上面是Test方法,其实两者是差不多,后者多了一个主键类,然后映射文件那边composite-id 加上了name和class,操作的时候有些变动。呵呵。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics