百味皆苦 java后端开发攻城狮

hibernate基础(二)

2019-05-23
百味皆苦

Session

  • Session 接口是 Hibernate 向应用程序提供的操纵数据库的最主要的接口, 它提供了基本的保存, 更新, 删除和加载 Java 对象的方法
  • Session 具有一个缓存, 位于缓存中的对象称为持久化对象, 它和数据库中的相关记录对应
  • Session 能够在某些时间点, 按照缓存中对象的变化来执行相关的 SQL 语句, 来同步更新数据库, 这一过程被称为刷新缓存(flush)
  • 站在持久化的角度, Hibernate 把对象分为 4 种状态: 持久化状态, 临时状态, 游离状态, 删除状态
  • Session 的特定方法能使对象从一个状态转换到另一个状态

缓存

  • 在 Session 接口的实现中包含一系列的 Java 集合, 这些 Java 集合构成了 Session 缓存
  • 只要 Session 实例没有结束生命周期, 且没有清理缓存,则存放在它缓存中的对象也不会结束生命周期
  • Session 缓存可减少 Hibernate 应用程序访问数据库的频率
Session缓存(持久化对象)---------flush()---------->数据库(记录)
数据库(记录)-------------------reflesh()-------->Session缓存(持久化对象)
Session缓存(持久化对象)--------clear()----------->Session缓存(空)
  • flush:Session 按照缓存中对象的属性变化来同步更新数据库
  • flush 缓存的例外情况: 如果对象使用 native 生成器生成 OID, 那么当调用 Session 的 save() 方法保存对象时, 会立即执行向数据库插入该实体的 insert 语句
  • commit() 和 flush() 方法的区别:flush 执行一系列 sql 语句,但不提交事务;commit 方法先调用flush() 方法,然后提交事务. 意味着提交事务意味着对数据库操作永久保存下来
  • 若希望改变 flush 的默认时间点, 可以通过 Session 的 setFlushMode() 方法显式设定 flush 的时间点

  • 默认情况下 Session 在以下时间点刷新缓存:
  • 显式调用 Session 的 flush() 方法
  • 当应用程序调用 Transaction 的 commit()方法的时, 该方法先 flush ,然后在向数据库提交事务
  • 当应用程序执行一些查询(HQL, Criteria)操作时,如果缓存中持久化对象的属性已经发生了变化,会先 flush 缓存,以保证查询结果能够反映持久化对象的最新状态

隔离级别

  • 一个事务与其他事务隔离的程度称为隔离级别
  • 隔离级别越高, 数据一致性就越好, 但并发性越弱

  • 对于同时运行的多个事务, 当这些事务访问数据库中相同的数据时, 如果没有采取必要的隔离机制, 就会导致各种并发问题

  • 脏读不可重复读幻读

  • 数据库事务的隔离性: 数据库系统必须具有隔离并发运行各个事务的能力, 使它们不会相互影响, 避免各种并发问题

  • Mysql 支持 4 中事务隔离级别. Mysql 默认的事务隔离级别为: REPEATABLE READ

    Hibernate 通过为 Hibernate 映射文件指定 hibernate.connection.isolation 属性来设置事务的隔离级别(1. READ UNCOMMITED;2. READ COMMITED;4. REPEATABLE READ;8. SERIALIZEABLE)

对象状态

临时对象

  • 在使用代理主键的情况下, OID 通常为 null
  • 不处于 Session 的缓存中
  • 在数据库中没有对应的记录

持久对象

  • OID 不为 null
  • 位于 Session 缓存中
  • 若在数据库中已经有和其对应的记录, 持久化对象和数据库中的相关记录对应
  • Session 在 flush 缓存时, 会根据持久化对象的属性变化, 来同步更新数据库
  • 在同一个 Session 实例的缓存中, 数据库表中的每条记录只对应唯一的持久化对象

删除对象

  • 在数据库中没有和其 OID 对应的记录
  • 不再处于 Session 缓存中
  • 一般情况下, 应用程序不该再使用被删除的对象

游离对象

  • OID 不为 null
  • 不再处于 Session 缓存中
  • 一般情况需下, 游离对象是由持久化对象转变过来的, 因此在数据库中可能还存在与它对应的记录

单向多对一

  • 单向 n-1 关联只需从 n 的一端可以访问 1 的一端
  • 在Order 类中定义一个 Customer 属性, 而在 Customer 类中无需定义存放 Order 对象的集合属性
  • <many-to-one> 元素来映射组成关系
  • name: 设定待映射的持久化类的属性的名字
  • column: 设定和持久化类的属性对应的表的外键
  • class:设定待映射的持久化类的属性的类型
<many-to-one
	name="customer"
	class="Customer"
	column="CUSTOMER_ID"
	not-null="true" />
  • user表
userid int(11) notnull primarykey 主键
name varchar cannull 
password varchar cannull
address_id int cannull mul
  • address表
addressid int notnull pri 主键
addressinfo varchar
public class User {
	private int userid; 				// User类的标识属性
	private String name; 			//name属性
	private String password;			//password属性
	private Address address; 			// User类的关联实体属性
	//无参构造方法
	public User() {                                                                   
	}
	//初始化所有User属性的构造方法
	public User(int userid, String name, String password, String type, Address address) {
		this.userid = userid;
		this.name = name;
		this.password = password;
		this.address = address;
	}
	// getter和setter方法

}

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2012-10-31 20:36:01 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="User" table="USER">
        <id name="userid" type="int" access="field">
            <column name="USERID" />
            <generator class="identity"/>
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        <property name="password" type="java.lang.String">
            <column name="PASSWORD" />
        </property>
        <!--用来映射多对一关联实体,column属性指定外键列列名-->
       <many-to-one name="address" class="Address" unique="true" fetch="join">
       		<column name="address_id" />
       </many-to-one>
    </class>
</hibernate-mapping>


public class Address {
//Address类的标识属性
private int addressid;
    private String addressinfo;
	//无参构造方法
	public Address () {
	}
	//初始化所有Address属性的构造方法
	public Address (int addressid, String addressinfo) {
		this.addressid = addressid;
		this.addressinfo = addressinfo;
	}
	//getter和setter方法

}


<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2012-10-31 20:36:01 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="Address" table="ADDRESS">
        <id name="addressid" type="int" access="field">
            <column name="ADDRESSID" />
            <generator class="identity" />
        </id>
        <property name="addressinfo" type="java.lang.String">
            <column name="ADDRESSINFO" />
        </property>
    </class>
</hibernate-mapping>

双向一对多

  • 双向 1-n 与 双向 n-1 是完全相同的两种情形
  • 双向 1-n 需要在 1 的一端可以访问 n 的一端, 反之依然
  • 从 Order 到 Customer 的多对一双向关联需要在Order 类中定义一个 Customer 属性, 而在 Customer 类中需定义存放 Order 对象的集合属性
  • 当 Session 从数据库中加载 Java 集合时, 创建的是 Hibernate内置集合类的实例, 因此在持久化类中定义集合属性时必须把属性声明为Java 接口类型
  • Hibernate 使用 <set> 元素来映射 set 类型的属性
<set name="orders">
	<key column="CUSTOMER_ID" />
	<one-to-many class="Order" />
</set>
  • 在hibernate中通过对 inverse 属性的来决定是由双向关联的哪一方来维护表和表之间的关系
  • inverse = false 的为主动方,inverse = true 的为被动方
  • 由主动方负责维护关联关系
  • 在没有设置 inverse=true 的情况下,父子两边都维护父子关系
  • 在 1-n 关系中,将 n 方设为主控方将有助于性能改善

  • user表
userid int(11) notnull primarykey 主键
name varchar cannull 
password varchar cannull
  • address表
addressid int notnull pri 主键
addressinfo varchar
user_id int notnull mul
import java.util.HashSet;
import java.util.Set;

public class User {
	private int userid; 											// User类的标识属性
	private String name; 											//name属性
	private String password;										//password属性
	private Set<Address> addresses=new HashSet<Address>(); 			// User类的关联实体属性
	//无参构造方法
	public User() {                                                                   
	}
	//初始化所有User属性的构造方法
	public User(int userid, String name, String password, String type, Address address) {
		this.userid = userid;
		this.name = name;
		this.password = password;
	}
	//getter和setter方法

}

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2012-11-3 10:29:42 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="User" table="USER">
        <id name="userid" type="int" access="field">
            <column name="USERID" />
            <generator class="identity" />
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        <property name="password" type="java.lang.String">
            <column name="PASSWORD" />
        </property>
        <!--映射集合属性,关联到持久化类。由Address一方控制关联关系-->
        <set name="addresses" table="ADDRESS" inverse="true" lazy="true">
            <key>
                <column name="USER_ID" />
            </key>
            <one-to-many class="Address" />
        </set>
    </class>
</hibernate-mapping>


public class Address {
//Address类的标识属性
	private int addressid;
    private String addressinfo;
    private User user;
	//无参构造方法
	public Address () {
	}
	//初始化所有Address属性的构造方法
	public Address (int addressid, String addressinfo) {
		this.addressid = addressid;
		this.addressinfo = addressinfo;
	}
	//getter和setter方法

}


<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2012-11-3 10:29:42 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="Address" table="ADDRESS">
        <id name="addressid" type="int" access="field">
            <column name="ADDRESSID" />
            <generator class="identity" />
        </id>
        <property name="addressinfo" type="java.lang.String">
            <column name="ADDRESSINFO" />
        </property>
        <many-to-one name="user" class="User" fetch="join">
            <column name="USER_ID" not-null="true"/>
        </many-to-one>
    </class>
</hibernate-mapping>

单向一对一

基于外键

  • 对于基于外键的1-1关联,其外键可以存放在任意一边,比如一个用户对应一个地址
  • 在需要存放外键一端,增加many-to-one元素
  • 为many-to-one元素增加unique=“true” 属性来表示为1-1关联
<many-to-one 
	name="manager" 
	class="Manager" 
	column="MANAGER_ID"
	cascade="all"
	unique="true" />
  • 另一端需要使用one-to-one元素,该元素使用 property-ref 属性指定使用被关联实体主键以外的字段作为关联字段
<one-to-one
	name="dept"
	class="Department"
	property-ref="manager" />
  • user表
userid int(11) notnull primarykey 主键
name varchar cannull 
password varchar cannull
address_id int cannull mul
  • address表
addressid int notnull pri 主键
addressinfo varchar
public class User {
	private int userid; 				// User类的标识属性
	private String name; 			//name属性
	private String password;			//password属性
	private Address address; 			// User类的关联实体属性
	//无参构造方法
	public User() {                                                                   
	}
	//初始化所有User属性的构造方法
	public User(int userid, String name, String password, String type, Address address) {
		this.userid = userid;
		this.name = name;
		this.password = password;
		this.address = address;
	}
	// getter和setter方法
}

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2012-10-31 20:36:01 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="User" table="USER">
        <id name="userid" type="int" access="field">
            <column name="USERID" />
            <generator class="identity"/>
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        <property name="password" type="java.lang.String">
            <column name="PASSWORD" />
        </property>
        <!--映射关联实体Address,将其address属性映射为address表中的外键address_id,unique指定为一对一映射-->
       <many-to-one name="address" class="Address" unique="true">
       		<column name="ADDRESS_ID" />
       </many-to-one>
    </class>
</hibernate-mapping>


public class Address {
	//Address类的标识属性
	private int addressid;
    private String addressinfo;
	//无参构造方法
	public Address () {
	}
	//初始化所有Address属性的构造方法
	public Address (int addressid, String addressinfo) {
		this.addressid = addressid;
		this.addressinfo = addressinfo;
	}
	//Address属性的getter和setter方法
	public int getAddressid () {
		return this.addressid;
	}
	public void setUseid(int addressid) {
		this.addressid = addressid;
	}
	//addressinfo的getter和setter方法
	public String getAddressinfo () {
		return this. addressinfo;
	}
	public void setAddressinfo (String addressinfo) {
		this. addressinfo = addressinfo;
	}
}


<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2012-10-31 20:36:01 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="Address" table="ADDRESS">
        <id name="addressid" type="int" access="field">
            <column name="ADDRESSID" />
            <generator class="identity" />
        </id>
        <property name="addressinfo" type="java.lang.String">
            <column name="ADDRESSINFO" />
        </property>
    </class>
</hibernate-mapping>

基于主键映射

  • 基于主键的映射策略:指一端的主键生成器使用 foreign 策略,表明根据”对方”的主键来生成自己的主键,自己并不能独立生成主键
  • <param> 子元素指定使用当前持久化类的哪个属性作为 “对方”
<id name="id" column="ID" type="integer">
	<generator class="foreign">
		<param name="property">manager</param>
	</generator>
</id>
  • 采用foreign主键生成器策略的一端增加 one-to-one 元素映射关联属性,其one-to-one属性还应增加 constrained=“true” 属性
  • 另一端增加one-to-one元素映射关联属性
  • constrained(约束):指定为当前持久化类对应的数据库表的主键添加一个外键约束,引用被关联的对象(“对方”)所对应的数据库表主键
<one-to-one
	name="manager"
	class="Manager"
	constrained="true" />
  • user表
userid int(11) notnull primarykey 主键
name varchar cannull 
password varchar cannull
  • address表
addressid int notnull pri 主键
addressinfo varchar
public class User {
	private int userid; 				// User类的标识属性
	private String name; 			//name属性
	private String password;			//password属性
	private Address address; 			// User类的关联实体属性
	//无参构造方法
	public User() {                                                                   
	}
	//初始化所有User属性的构造方法
	public User(int userid, String name, String password, String type, Address address) {
		this.userid = userid;
		this.name = name;
		this.password = password;
		this.address = address;
	}
	// getter和setter方法
	
}

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2012-10-31 20:36:01 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="User" table="USER">
        <id name="userid" type="int" access="field">
            <column name="USERID" />
            <!--基于主键关联时,将主键生成策略设置为foreign,表明由关联类来生成主键,即直接使用另一个关联类的主键值,该持久类本身不能生成主键-->
            <generator class="foreign">
            	<!--关联持久化类的属性名-->
            	<param name="property">address</param>
            </generator>
            
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        <property name="password" type="java.lang.String">
            <column name="PASSWORD" />
        </property>
        <!--基于主键的一对一关联映射-->
        <one-to-one name="address" class="Address" constrained="true">
        </one-to-one>
    </class>
</hibernate-mapping>


public class Address {
//Address类的标识属性
	private int addressid;
    private String addressinfo;
	//无参构造方法
	public Address () {
	}
	//初始化所有Address属性的构造方法
	public Address (int addressid, String addressinfo) {
		this.addressid = addressid;
		this.addressinfo = addressinfo;
	}
	//Address属性的getter和setter方法
	public int getAddressid () {
		return this.addressid;
	}
	public void setUseid(int addressid) {
		this.addressid = addressid;
	}
	//addressinfo的getter和setter方法
	public String getAddressinfo () {
		return this. addressinfo;
	}
	public void setAddressinfo (String addressinfo) {
		this. addressinfo = addressinfo;
	}
}


<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2012-10-31 20:36:01 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="Address" table="ADDRESS">
        <id name="addressid" type="int" access="field">
            <column name="ADDRESSID" />
            <generator class="identity" />
        </id>
        <property name="addressinfo" type="java.lang.String">
            <column name="ADDRESSINFO" />
        </property>
    </class>
</hibernate-mapping>

双向一对一

基于主键

  • user表
userid int(11) notnull primarykey 主键
name varchar cannull 
password varchar cannull
  • address表
addressid int notnull pri 主键
addressinfo varchar
public class User {
	private int userid; 				// User类的标识属性
	private String name; 			//name属性
	private String password;			//password属性
	private Address address; 			// User类的关联实体属性
	//无参构造方法
	public User() {                                                                   
	}
	//初始化所有User属性的构造方法
	public User(int userid, String name, String password, String type, Address address) {
		this.userid = userid;
		this.name = name;
		this.password = password;
		this.address = address;
	}
	//getter和setter方法

}

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2012-10-31 20:36:01 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="User" table="USER">
        <id name="userid" type="int" access="field">
            <column name="USERID" />
            <generator class="identity"/>  
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        <property name="password" type="java.lang.String">
            <column name="PASSWORD" />
        </property>
        <!--映射关联属性address.cascade=all表示级联保存User对象关联的Address对象-->
        <one-to-one name="address" class="Address" cascade="all">
        </one-to-one>
    </class>
</hibernate-mapping>


public class Address {
//Address类的标识属性
	private int addressid;
    private String addressinfo;
    private User user;
	//无参构造方法
	public Address () {
	}
	//初始化所有Address属性的构造方法
	public Address (int addressid, String addressinfo) {
		this.addressid = addressid;
		this.addressinfo = addressinfo;
	}
	//getter和setter方法
}


<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2012-10-31 20:36:01 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="Address" table="ADDRESS">
        <id name="addressid" type="int" access="field">
            <column name="ADDRESSID" />
            <generator class="foreign">
            	<param name="property">user</param>
            </generator>
        </id>
        <property name="addressinfo" type="java.lang.String">
            <column name="ADDRESSINFO" />
        </property>
        <!--映射关联属性user。constrained表示在address表中存在一个外键约束-->
        <one-to-one name="user" class="User" constrained="true">
        </one-to-one>
    </class>
</hibernate-mapping>

基于外键

  • user表
userid int(11) notnull primarykey 主键
name varchar cannull 
password varchar cannull
  • address表
addressid int notnull pri 主键
addressinfo varchar
user_id int notnull mul
public class User {
	private int userid; 				// User类的标识属性
	private String name; 			//name属性
	private String password;			//password属性
	private Address address; 			// User类的关联实体属性
	//无参构造方法
	public User() {                                                                   
	}
	//初始化所有User属性的构造方法
	public User(int userid, String name, String password, String type, Address address) {
		this.userid = userid;
		this.name = name;
		this.password = password;
		this.address = address;
	}
	//getter和setter方法

}

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2012-10-31 20:36:01 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="User" table="USER">
        <id name="userid" type="int" access="field">
            <column name="USERID" />
            <generator class="identity"/>  
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        <property name="password" type="java.lang.String">
            <column name="PASSWORD" />
        </property>
        <!--映射关联属性address。在保存User类的对象时,级联保存该对象所关联的address对象-->
        <one-to-one name="address" class="Address" cascade="all">
        </one-to-one>
    </class>
</hibernate-mapping>


public class Address {
//Address类的标识属性
	private int addressid;
    private String addressinfo;
    private User user;
	//无参构造方法
	public Address () {
	}
	//初始化所有Address属性的构造方法
	public Address (int addressid, String addressinfo) {
		this.addressid = addressid;
		this.addressinfo = addressinfo;
	}
	//getter和setter方法

	
}


<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2012-10-31 20:36:01 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="Address" table="ADDRESS">
        <id name="addressid" type="int" access="field">
            <column name="ADDRESSID" />
            <generator class="identity"/>
        </id>
        <property name="addressinfo" type="java.lang.String">
            <column name="ADDRESSINFO" />
        </property>
        <many-to-one name="user" class="User" fetch="select" unique="true">
        	<column name="USER_ID" />
        </many-to-one>
    </class>
</hibernate-mapping>

单向一对多

  • user表
userid int(11) notnull primarykey 主键
name varchar cannull 
password varchar cannull
  • address表
addressid int notnull pri 主键
addressinfo varchar
user_id int notnull mul
import java.util.HashSet;
import java.util.Set;

public class User {
	private int userid; 				// User类的标识属性
	private String name; 			//name属性
	private String password;			//password属性
	private Set<Address> addresses=new HashSet<Address>(); 				// User类的关联实体属性
	//无参构造方法
	public User() {                                                                   
	}
	//初始化所有User属性的构造方法
	public User(int userid, String name, String password, String type, Address address) {
		this.userid = userid;
		this.name = name;
		this.password = password;
	}
	//getter和setter方法

}

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2012-10-31 23:57:50 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="User" table="USER">
        <id name="userid" type="int" access="field">
            <column name="USERID" />
            <generator class="identity" />
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        <property name="password" type="java.lang.String">
            <column name="PASSWORD" />
        </property>
        <!--映射集合属性,inverse为false表示由User方来维护关联关系,不采用延迟加载-->
        <set name="addresses" table="ADDRESS" inverse="false" lazy="true">
            <key>
            	<!--确定关联的外键列-->
                <column name="USER_ID" />
            </key>
            <!--映射到关联类属性-->
            <one-to-many class="Address" />
        </set>
    </class>
</hibernate-mapping>


public class Address {
//Address类的标识属性
	private int addressid;
    private String addressinfo;
	//无参构造方法
	public Address () {
	}
	//初始化所有Address属性的构造方法
	public Address (int addressid, String addressinfo) {
		this.addressid = addressid;
		this.addressinfo = addressinfo;
	}
	//getter和setter方法
	
}


<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2012-10-31 23:57:50 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="Address" table="ADDRESS">
        <id name="addressid" type="int" access="field">
            <column name="ADDRESSID" />
            <generator class="identity" />
        </id>
        <property name="addressinfo" type="java.lang.String">
            <column name="ADDRESSINFO" />
        </property>
    </class>
</hibernate-mapping>

单向多对多

  • 它利用中间表将两个主表关联起来。
  • 中间表的作用是将两张表的主键作为其外键,通过外键建立这两张表之间的映射关系
  • 比如多个用户User对应多个地址Address
  • user表
userid int(11) notnull primarykey 主键
name varchar cannull 
password varchar cannull
  • address表
addressid int notnull pri 主键
addressinfo varchar
  • user_address表
addressid int notnull pri
userid int notnull pri
import java.util.HashSet;
import java.util.Set;

public class User {
	private int userid; 				// User类的标识属性
	private String name; 			//name属性
	private String password;			//password属性
	private Set<Address> addresses=new HashSet<Address>(); // User类的关联实体属性
	//无参构造方法
	public User() {                                                                   
	}
	//初始化所有User属性的构造方法
	public User(int userid, String name, String password, String type, Address address) {
		this.userid = userid;
		this.name = name;
		this.password = password;
	}
	//省略get和set
}

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2012-10-31 23:57:50 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="User" table="USER">
        <id name="userid" type="int" access="field">
            <column name="USERID" />
            <generator class="identity" />
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        <property name="password" type="java.lang.String">
            <column name="PASSWORD" />
        </property>
        <!--映射集合属性,USER_ADDRESS是中间表名称,由User一方来维护关联关系,不采用延迟加载-->
        <set name="addresses" table="USER_ADDRESS" inverse="false" lazy="true">
            <key>
                <column name="USERID" /><!--指定USER表关联到中间表的外键列名-->
            </key>
            <!--指定关联USER表的Address对象的主键在连接表中的列名-->
            <many-to-many class="Address" column="ADDRESSID"/>
        </set>
    </class>
</hibernate-mapping>


public class Address {
//Address类的标识属性
	private int addressid;
    private String addressinfo;
	//无参构造方法
	public Address () {
	}
	//初始化所有Address属性的构造方法
	public Address (int addressid, String addressinfo) {
		this.addressid = addressid;
		this.addressinfo = addressinfo;
	}
	//Address属性的getter和setter方法
	public int getAddressid () {
		return this.addressid;
	}
	public void setUseid(int addressid) {
		this.addressid = addressid;
	}
	//addressinfo的getter和setter方法
	public String getAddressinfo () {
		return this. addressinfo;
	}
	public void setAddressinfo (String addressinfo) {
		this. addressinfo = addressinfo;
	}
}


<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2012-10-31 23:57:50 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="Address" table="ADDRESS">
        <id name="addressid" type="int" access="field">
            <column name="ADDRESSID" />
            <generator class="identity" />
        </id>
        <property name="addressinfo" type="java.lang.String">
            <column name="ADDRESSINFO" />
        </property>
    </class>
</hibernate-mapping>

双向多对多

  • 双向 n-n 关联需要两端都使用集合属性
  • 双向n-n关联必须使用连接表
  • 集合属性应增加 key 子元素用以映射外键列, 集合元素里还应增加many-to-many子元素关联实体类
  • 对于双向 n-n 关联, 必须把其中一端的 inverse 设置为 true, 否则两端都维护关联关系可能会造成主键冲突

  • user表
userid int(11) notnull primarykey 主键
name varchar cannull 
password varchar cannull
  • address表
addressid int notnull pri 主键
addressinfo varchar
  • user_address表
addressid int notnull pri
userid int notnull pri
import java.util.HashSet;
import java.util.Set;

public class User {
	private int userid; 				// User类的标识属性
	private String name; 			//name属性
	private String password;			//password属性
	private Set<Address> addresses=new HashSet<Address>(); 	// User类的关联实体属性
	//无参构造方法
	public User() {                                                                   
	}
	//初始化所有User属性的构造方法
	public User(int userid, String name, String password, String type, Address address) {
		this.userid = userid;
		this.name = name;
		this.password = password;
	}
	//省略get和set

}

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2012-10-31 23:57:50 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="User" table="USER">
        <id name="userid" type="int" access="field">
            <column name="USERID" />
            <generator class="identity" />
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        <property name="password" type="java.lang.String">
            <column name="PASSWORD" />
        </property>
        <!--映射集合属性,关联到持久化类,table="user_address"指定了中间表名称-->
        <set name="addresses" table="USER_ADDRESS" inverse="true" lazy="true">
            <key>
                <column name="USERID" />
            </key>
            <many-to-many class="Address" column="ADDRESSID"/>
        </set>
    </class>
</hibernate-mapping>

import java.util.HashSet;
import java.util.Set;


public class Address {
//Address类的标识属性
	private int addressid;
    private String addressinfo;
    private Set<User> users = new HashSet<User>();	
	//无参构造方法
	public Address () {
	}
	//初始化所有Address属性的构造方法
	public Address (int addressid, String addressinfo) {
		this.addressid = addressid;
		this.addressinfo = addressinfo;
	}
	//Address属性的getter和setter方法
	public int getAddressid () {
		return this.addressid;
	}
	public void setUseid(int addressid) {
		this.addressid = addressid;
	}
	//addressinfo的getter和setter方法
	public String getAddressinfo () {
		return this. addressinfo;
	}
	public void setAddressinfo (String addressinfo) {
		this. addressinfo = addressinfo;
	}
	public Set<User> getUsers() {
		return users;
	}
	public void setUsers(Set<User> users) {
		this.users = users;
	}
}


<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2012-11-2 11:19:47 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="Address" table="ADDRESS">
        <id name="addressid" type="int" access="field">
            <column name="ADDRESSID" />
            <generator class="identity" />
        </id>
        <property name="addressinfo" type="java.lang.String">
            <column name="ADDRESSINFO" />
        </property>
        <!--映射集合属性,关联到持久化类,table属性指定了中间表名字-->
        <set name="users" table="USER_ADDRESS" inverse="false" lazy="true">
            <key>
                <column name="ADDRESSID" />
            </key>
            <many-to-many class="User" column="USERID"/>
        </set>
    </class>
</hibernate-mapping>


Comments

Content