1. 程式人生 > >【JavaEE學習筆記】Hibernate_06_註解開發,getCurrentSession(),對映關係

【JavaEE學習筆記】Hibernate_06_註解開發,getCurrentSession(),對映關係

Hibernate_06

A.註解

1.概述

每個持久化POJO類都是一個實體Bean

通過在類的定義中使用@Entity註解來進行宣告

目前定義屬性對應的列時有兩種定義方法

a.定義在屬性上

b.定義在get方法上

兩種方法是等價的,目前沒有選擇標準,但一個類中只能使用一種方法

2.常用欄位屬性

name="cloumnName" 當前屬性對應的列名,如果列名稱和屬性名稱一致,可以省略
boolean unique() default false 是否在該列上設定唯一約束,一般開發階段不建議定義大量的約束
boolean nullable() default true 設定對應的列是否允許為空
boolean insertable() default true 該列是否作為生成insert語句的一個列
boolean updatable() default true 該列是否作為生成update語句的一個列
String columnDefinition() default 直接定義對應列的配置,但是會導致跨資料庫平臺性的丟失
String table() default "" 定義對應的表  default是主表
int length() default 255 針對字串型別的列定義長度
int percision() default 0 針對數字型別的列定義數值精度
int scale() default 0 針對數值型別的列定義數值精度,這裡定義小數位數

3.常用註解

Entity 定義實體類
Column 定義屬性
Temporal 用於給日期型別定義獲時的精度:Date獲取日期,Time獲取時間,Timestamp獲取日期時間
Transient,Basic 所有非static非transient屬性都可以被持久化,除非用transient註解,預設都為Basic
Id 可以將某個屬性定義為主鍵
GenerateValue 定義該識別符號的生成策略
AUTO 可以是identity column,squence或者table型別,取決於不同底層的資料庫

4.使用步驟

匯入hibernate,mysql驅動

建立UserBean

package org.wpf.entity;

import java.io.Serializable;
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

// 定義為實體類,資料庫中的表名為t_users
@Entity(name = "t_users")
public class UserBean implements Serializable {

	private static final long serialVersionUID = -5771488248839932252L;

	// 主鍵
	@Id
	// 定義識別符號生成策略
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;

	// 長度為20,不能為空,唯一
	@Column(length = 20, nullable = false, unique = true)
	private String username;

	// 長度為20,不能為空
	@Column(length = 20, nullable = false)
	private String password;

	// 獲取日期
	@Temporal(TemporalType.DATE)
	// 設定該列值預設為系統當前時間
	@Column(columnDefinition = "timestamp default current_timestamp")
	private Date birth;

	// 寬度為8,精度為2
	@Column(precision = 8, scale = 2)
	private Double salary;

	// 預設值為1
	@Column(columnDefinition = "boolean default 1")
	private boolean sex;

	public Long getId() {
		return id;
	}

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

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public Date getBirth() {
		return birth;
	}

	public void setBirth(Date birth) {
		this.birth = birth;
	}

	public Double getSalary() {
		return salary;
	}

	public void setSalary(Double salary) {
		this.salary = salary;
	}

	public boolean isSex() {
		return sex;
	}

	public void setSex(boolean sex) {
		this.sex = sex;
	}

}

配置hibernate.cfg.xml檔案

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
                                         "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
	<session-factory>
		<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
		<property name="hibernate.connection.password">root</property>
		<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8</property>
		<property name="hibernate.connection.username">root</property>
		<property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
		<property name="hibernate.show_sql">true</property>
		<property name="hibernate.format_sql">true</property>
		<property name="hibernate.hbm2ddl.auto">update</property>
		
		<!-- 此處對映為javaBean -->
		<mapping class="org.wpf.entity.UserBean" />
	</session-factory>
</hibernate-configuration>
測試類
package org.wpf.entity;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.service.ServiceRegistry;

public class Demo01 {
	public static void main(String[] args) {
		ServiceRegistry sr = new StandardServiceRegistryBuilder().configure().build();
		SessionFactory fac = new MetadataSources(sr).buildMetadata().buildSessionFactory();
		Session session = fac.openSession();
		Transaction tx = session.beginTransaction();
		UserBean u1 = new UserBean();
		u1.setUsername("zhangsan");
		u1.setPassword("123456");
		session.save(u1);
		tx.commit();
		session.close();
		fac.close();
	}
}
檢視控制檯


檢視資料庫表


檢視資料


5.annotation主鍵生成策略

一般情況下都是使用annoation的標準註解

標準的annotation方式的主鍵生成策略:auto table identity squence

table使用表儲存id(建立一張專門儲存id的表,記錄對應的表的對應最大id值)

@javax.persistence.TableGenerator(

name="EMP_GEN",生成器的名稱

table="GENERATOR_TABLE",額外表的名稱

pkColumnName="key",額外表的主鍵列的名稱

valueColumnName="hi",額外表的id值對應列的名稱

pkColumnValue="EMP",額外表的主鍵列的值

allocationSize=20,額外表的id增長的步長值

)

package org.wpf.entity;

import java.io.Serializable;
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.TableGenerator;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

// 定義為實體類,資料庫中的表名為t_users
@Entity(name = "t_users")
public class UserBean implements Serializable {

	private static final long serialVersionUID = -5771488248839932252L;

	// 主鍵生成策略
	@TableGenerator(name = "EMP_GEN", 
					table = "GENERATOR_TABLE", 
					pkColumnName = "key1", 
					valueColumnName = "hi", 
					pkColumnValue = "abc", 
					allocationSize = 20)
	// 主鍵
	@Id
	// 定義識別符號生成策略
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;

	// 長度為20,不能為空,唯一
	@Column(length = 20, nullable = false, unique = true)
	private String username;

	// 長度為20,不能為空
	@Column(length = 20, nullable = false)
	private String password;

	// 獲取日期
	@Temporal(TemporalType.DATE)
	// 設定該列值預設為系統當前時間
	@Column(columnDefinition = "timestamp default current_timestamp")
	private Date birth;

	// 寬度為8,精度為2
	@Column(precision = 8, scale = 2)
	private Double salary;

	// 預設值為1
	@Column(columnDefinition = "boolean default 1")
	private boolean sex;

	public Long getId() {
		return id;
	}

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

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public Date getBirth() {
		return birth;
	}

	public void setBirth(Date birth) {
		this.birth = birth;
	}

	public Double getSalary() {
		return salary;
	}

	public void setSalary(Double salary) {
		this.salary = salary;
	}

	public boolean isSex() {
		return sex;
	}

	public void setSex(boolean sex) {
		this.sex = sex;
	}

}

B.getCurrentSession

1.openSession()和getCurrentSession()區別

openSession()每次都會新建一個Session

getCurrentSession首先從上下文中查詢是否有session,有則獲取,無則新建

getCurrentSession需要有對應的事物支援,當事務結束時會自動關閉session

openSession必須手動關閉

getCurrentSession的使用需要有額外配置

<property name="hibernate.current_session_context_class">thread</property>

2.引入getCurrentSession()後的工具類

package org.wpf.util;

import org.hibernate.HibernateException;
import org.hibernate.SessionFactory;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.service.ServiceRegistry;

public class HibernateSessionFactory {
	private static SessionFactory sessionFactory;

	static {
		buildSessionFactory();
	}

	// 私有構造
	private HibernateSessionFactory() {
	}

	// 獲取SessionFactory
	public static SessionFactory getSessionFactory() {
		return sessionFactory;
	}
	
	// 建立session工廠
	private static void buildSessionFactory() throws HibernateException {
		// 如果沒有
		if (sessionFactory == null) {
			ServiceRegistry sr = new StandardServiceRegistryBuilder().configure().build();
			sessionFactory = new MetadataSources(sr).buildMetadata().buildSessionFactory();
		}
	}
}

3.過濾器

package org.wpf.fliter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.wpf.util.HibernateSessionFactory;

public class OpenSessionInViewFilter implements Filter {

	@Override
	public void destroy() {
	}

	@Override
	public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
			throws IOException, ServletException {
		try {
			// 開啟事物
			HibernateSessionFactory.getSessionFactory().getCurrentSession().beginTransaction();
			// 放行
			arg2.doFilter(arg0, arg1);
			// 提交事物
			HibernateSessionFactory.getSessionFactory().getCurrentSession().getTransaction().commit();
		} catch (Exception e) {
			// 回滾
			HibernateSessionFactory.getSessionFactory().getCurrentSession().getTransaction().rollback();
		}
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {
	}

}

C.對映關係

1.常見對映關係

一對一

一對多或多對一

多對多

關聯關係實際開發中可以分為單向關聯和雙相關聯

2.一對多查詢

一對多或多對一的關聯在實際開發中用的比較多

一個簡單的例子就是客戶與訂單的關係

一個客戶可能發出多個訂單,而每個訂單隻屬於一個客戶

這樣,如果從客戶指向訂單,這種關係就屬於一對多的關係


在關係資料庫中,只有存在外來鍵參照關係,而且總是由many方參照one方

因此,在關係資料庫中,實際支援多對一或一對一的單項關聯即可

3.Oracle中的SQL可以分為4大類

DDL資料定義語言 create drop alter truncate

DML資料操縱語言 insert update delete select

DCL資料控制語言 grant revoke [with admin option 和 with grant option]

TCL事物控制語言 commit rollback savepoint

4.截斷操作 truncate table t_users

truncate屬於DDL,沒有事物的概念,刪除後沒有辦法恢復

不會記錄日誌資訊,所以刪除大量資料時,執行效率遠高於delete from

5.定義一對多

一方Customer

package org.wpf.entity;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

public class Customer implements Serializable {
	private static final long serialVersionUID = 4313768320545350900L;
	
	private Long id;
	private String name;
	// 這是類中表示1對多關聯的方式,表示一個Customer中包含了多個Order
	private Set<Order> orders = new HashSet<>(0);

	public Long getId() {
		return id;
	}

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

	public String getName() {
		return name;
	}

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

	public Set<Order> getOrders() {
		return orders;
	}

	public void setOrders(Set<Order> orders) {
		this.orders = orders;
	}

	@Override
	public String toString() {
		return "Customer [id=" + id + ", name=" + name + ", orders=" + orders + "]";
	}

}

Customer.hbm.xml

<?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>
	<class name="org.wpf.entity.Customer" table="t_customer">
		<id name="id" type="java.lang.Long">
			<column name="ID" />
			<generator class="identity" />
		</id>
		<property name="name" type="java.lang.String">
			<column name="NAME" length="20" not-null="true" />
		</property>
		<set name="orders" inverse="true" cascade="all">
			<key>
				<column name="customer_id" not-null="true" />
			</key>
			<one-to-many class="org.wpf.entity.Order" />
		</set>
	</class>
</hibernate-mapping>

多方Order

package org.wpf.entity;

import java.io.Serializable;
import java.util.Date;

public class Order implements Serializable {

	private static final long serialVersionUID = 5875230206918806994L;
	
	private Long id;
	private Customer customer;
	private Date oDate;

	public Long getId() {
		return id;
	}

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

	public Customer getCustomer() {
		return customer;
	}

	public void setCustomer(Customer customer) {
		this.customer = customer;
	}

	public Date getoDate() {
		return oDate;
	}

	public void setoDate(Date oDate) {
		this.oDate = oDate;
	}

	@Override
	public String toString() {
		return "Order [id=" + id + ", customer=" + customer + ", oDate=" + oDate + "]";
	}

}

Order.hbm.xml

<?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>
	<class name="org.wpf.entity.Order" table="T_ORDER">
		<id name="id" type="java.lang.Long">
			<column name="ID" />
			<generator class="identity" />
		</id>
		<many-to-one name="customer" class="org.wpf.entity.Customer"
			fetch="select">
			<column name="customer_id" not-null="true" />
		</many-to-one>
		<property name="oDate" type="java.util.Date">
			<column name="odate" length="19" not-null="true" />
		</property>
	</class>
</hibernate-mapping>

在配置檔案中新增對映

  <mapping resource="org/wpf/entity/Customer.hbm.xml"/>
  <mapping resource="org/wpf/entity/Order.hbm.xml"/>
測試類
package org.wpf.entity;

import java.util.Date;

import org.hibernate.Session;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.wpf.util.HibernateSessionFactory;

class Test01 {

	@BeforeEach
	void setUp() throws Exception {
		HibernateSessionFactory.getSessionFactory().getCurrentSession().beginTransaction();
	}

	@AfterEach
	void tearDown() throws Exception {
		HibernateSessionFactory.getSessionFactory().getCurrentSession().getTransaction().commit();
	}

	@Test
	void test() {
		// 級聯需要互相通知
		Customer c1 = new Customer();
		c1.setName("Tom");
		
		Order o1 = new Order();
		o1.setoDate(new Date());
		
		Order o2 = new Order();
		o2.setoDate(new Date());
		
		// 相互通知
		c1.getOrders().add(o1);
		o1.setCustomer(c1);
		c1.getOrders().add(o2);
		o2.setCustomer(c1);
		
		Session session = HibernateSessionFactory.getSessionFactory().getCurrentSession();
		session.save(c1);
	}

}
控制檯資訊
Hibernate: 
    
    create table t_customer (
       ID bigint not null auto_increment,
        NAME varchar(20) not null,
        primary key (ID)
    ) engine=InnoDB
Hibernate: 
    
    create table T_ORDER (
       ID bigint not null auto_increment,
        customer_id bigint not null,
        odate datetime not null,
        primary key (ID)
    ) engine=InnoDB
Hibernate: 
    
    alter table T_ORDER 
       add constraint FKfiait2tmbi08bkn450b9c5i54 
       foreign key (customer_id) 
       references t_customer (ID)
Hibernate: 
    insert 
    into
        t_customer
        (NAME) 
    values
        (?)
Hibernate: 
    insert 
    into
        T_ORDER
        (customer_id, odate) 
    values
        (?, ?)
Hibernate: 
    insert 
    into
        T_ORDER
        (customer_id, odate) 
    values
        (?, ?)
執行結果


6.inverse和cascade

inverse的真正作用就是指定由哪一方來維護之間的關聯關係

當一方中制訂了inverse=false預設,那麼那一方就有責任負責之間的關聯關係

就是hibernate如何生成sql來維護關聯的記錄

區別:

Inverse負責控制關係,預設為false,也就是兩端都能控制

但造成一些問題,更新時會因為兩端都控制,於是重複更新

一般有一端要設為true

cascade負責控制關聯物件的級聯操作,包括更新,刪除等

也就是說對一個物件進行更新,刪除時,其他物件也受影響

那麼跟他是多對一的關係的物件也全部被刪除

7.其他屬性

<set>元素包括以下屬性

name:設定待對映的持久化類的屬性名

cascade:當取值為save_update時,表示級聯儲存和更新

<set>元素還可以包括<key>和<one-to-many>兩個子元素

<key>元素設定與所關聯的持久化類對應表的外來鍵

<one-to-many>元素設定所關聯的持久化類

<many-to-one>元素建立了訂單和客戶表的外來鍵之間的對映

name:設定待對映的持久化類的屬性名

column:設定和持久化類的屬性對應的表的外來鍵

class:設定持久化類的屬性型別

not-null:如果為true,表示客戶屬性不允許為空

fetech="select":抓取策略的設定,表示獲取訂單後如何獲取對應的客戶資訊

將fetch修改為join,表示獲取客戶資訊時不是採用傳送額外的select語句進行獲取,而是採用inner join的方式直接查詢客戶資訊,不會產生額外的SQL語句,採用這樣的方式查詢效率會略高於傳送額外查詢的方式

8.註解定義的方式

customer

package org.wpf.entity;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;

@Entity(name = "t_customer")
public class Customer implements Serializable {
	private static final long serialVersionUID = 4313768320545350900L;
	
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;
	
	@Column(length = 32, nullable = false)
	private String name;

	@OneToMany(mappedBy = "customer", cascade = CascadeType.ALL)
	@OrderBy("id desc")
	private Set<Order> orders = new HashSet<>(0);

	public Long getId() {
		return id;
	}

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

	public String getName() {
		return name;
	}

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

	public Set<Order> getOrders() {
		return orders;
	}

	public void setOrders(Set<Order> orders) {
		this.orders = orders;
	}

	@Override
	public String toString() {
		return "Customer [id=" + id + ", name=" + name + ", orders=" + orders + "]";
	}

}

order

package org.wpf.entity;

import java.io.Serializable;
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;

@Entity(name = "t_order")
public class Order implements Serializable {

	private static final long serialVersionUID = 5875230206918806994L;

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;

	@Column(name = "all_price", precision = 8, scale = 2)
	private Double allPrice;

	@ManyToOne(optional = false)
	@JoinColumn(name = "customer_id")
	private Customer customer;

	public Long getId() {
		return id;
	}

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

	public Customer getCustomer() {
		return customer;
	}

	public void setCustomer(Customer customer) {
		this.customer = customer;
	}

	public Double getAllPrice() {
		return allPrice;
	}

	public void setAllPrice(Double allPrice) {
		this.allPrice = allPrice;
	}

	@Override
	public String toString() {
		return "Order [id=" + id + ", allPrice=" + allPrice + ", customer=" + customer + "]";
	}

}

設定配置檔案

  <mapping class="org.wpf.entity.Customer"/>
  <mapping class="org.wpf.entity.Order"/>
執行結果
Hibernate: 
    
    create table t_customer (
       id bigint not null auto_increment,
        name varchar(32) not null,
        primary key (id)
    ) engine=InnoDB
Hibernate: 
    
    create table t_order (
       id bigint not null auto_increment,
        all_price double precision,
        customer_id bigint not null,
        primary key (id)
    ) engine=InnoDB
Hibernate: 
    
    alter table t_order 
       add constraint FKesy3n2gc3fa0s3trrk3tvyv9a 
       foreign key (customer_id) 
       references t_customer (id)
Hibernate: 
    insert 
    into
        t_customer
        (name) 
    values
        (?)
Hibernate: 
    insert 
    into
        t_order
        (all_price, customer_id) 
    values
        (?, ?)
Hibernate: 
    insert 
    into
        t_order
        (all_price, customer_id) 
    values
        (?, ?)


9.一對一

實現方式:

共享主鍵和唯一外來鍵


10.共享主鍵

既是主鍵,又是外來鍵,主控方和受控方

a.xml

Person主控方

package org.wpf.entity;

import java.io.Serializable;

public class Person implements Serializable {

	private static final long serialVersionUID = -6446631496216328660L;
	private Long id;
	private String name;
	private Card card;

	public Person() {
		super();
	}

	public Person(Long id, String name, Card card) {
		super();
		this.id = id;
		this.name = name;
		this.card = card;
	}

	public Long getId() {
		return id;
	}

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

	public String getName() {
		return name;
	}

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

	public Card getCard() {
		return card;
	}

	public void setCard(Card card) {
		this.card = card;
	}

}

Person.hbm.xml

<?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 2018-1-22 22:27:49 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
	<class name="org.wpf.entity.Person" table="t_person">
		<id name="id" type="java.lang.Long">
			<column name="ID" />
			<generator class="identity" />
		</id>
		<property name="name" type="java.lang.String">
			<column name="NAME" length="10" not-null="true" />
		</property>
		<one-to-one name="card" class="org.wpf.entity.Card"
			cascade="all"></one-to-one>
	</class>
</hibernate-mapping>

Card受控方

package org.wpf.entity;

import java.io.Serializable;

public class Card implements Serializable {

	private static final long serialVersionUID = 7490343597638703173L;
	private Long id;
	private Person person;
	private String city;

	public Card() {
		super();
	}

	public Card(Long id, Person person, String city) {
		super();
		this.id = id;
		this.person = person;
		this.city = city;
	}

	public Long getId() {
		return id;
	}

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

	public Person getPerson() {
		return person;
	}

	public void setPerson(Person person) {
		this.person = person;
	}

	public String getCity() {
		return city;
	}

	public void setCity(String city) {
		this.city = city;
	}

}

Card.hbm.xml

<?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 2018-1-22 22:27:49 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
	<class name="org.wpf.entity.Card" table="t_card" catalog="test">
		<id name="id" type="java.lang.Long">
			<column name="ID" />
			<!-- 表明根據對方的主鍵來生成自己的主鍵,自己並不能獨立生成主鍵 ,這裡表示身份證的主鍵值是從它屬性person的id值中獲取的 -->
			<generator class="foreign">
				<param name="property">person</param>
			</generator>
		</id>
		<!-- constrained="true"表示當前類是受控方,受Person的控制 -->
		<one-to-one name="person" class="org.wpf.entity.Person"
			constrained="true" />
		<property name="city" type="java.lang.String">
			<column name="CITY" length="32" />
		</property>
	</class>
</hibernate-mapping>

b.註解

Husband主控方

package org.wpf.entity;

import java.io.Serializable;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;

@Entity(name = "t_husband") // 主控方
public class Husband implements Serializable {
	private static final long serialVersionUID = 7204300104344481060L;

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;

	@Column(length = 20, nullable = false)
	private String name;

	@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "husband")
	private Wife wife;

	public Husband() {
		super();
	}

	public Husband(Long id, String name, Wife wife) {
		super();
		this.id = id;
		this.name = name;
		this.wife = wife;
	}

	public Long getId() {
		return id;
	}

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

	public String getName() {
		return name;
	}

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

	public Wife getWife() {
		return wife;
	}

	public void setWife(Wife wife) {
		this.wife = wife;
	}

}

Wife受控方

package org.wpf.entity;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;

import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;

@Entity(name = "t_wife")
public class Wife implements Serializable {
	private static final long serialVersionUID = -6685649713801290134L;

	@Id
	@GenericGenerator(name = "ff1", strategy = "foreign", parameters = {
			@Parameter(name = "property", value = "husband") })
	@GeneratedValue(generator = "ff1")
	private Long id;

	@Column(length = 32)
	private String name;

	@OneToOne(orphanRemoval = true)
	@PrimaryKeyJoinColumn
	private Husband husband;

	public Wife() {
		super();
	}

	public Wife(Long id, String name, Husband husband) {
		super();
		this.id = id;
		this.name = name;
		this.husband = husband;
	}

	public Long getId() {
		return id;
	}

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

	public String getName() {
		return name;
	}

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

	public Husband getHusband() {
		return husband;
	}

	public void setHusband(Husband husband) {
		this.husband = husband;
	}

}
@GenericGenerator(name = "foreignKey"

生成器名稱,供GeneratedValue中進行呼叫

strategy = "foreign"    使用hibernate的外來鍵策略

parameters = @Parameter(value = "article引數值",name = "property引數名稱"))//指定成員屬性中的article所在類的主鍵為本類的主鍵,這裡的引數屬性name必須為"property"

@GeneratedValue(generator = "foreignKey")//使用上述定義的id生成器

11.唯一外來鍵的關聯實現方式

a.xml(bean和上面的一樣,省略)

Husband.hbm.xml

<?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 2018-1-22 22:47:11 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
	<class name="org.wpf.entity.Husband" table="HUSBAND">
		<id name="id" type="java.lang.Long">
			<column name="ID" />
			<generator class="native" />
		</id>
		<property name="name" type="java.lang.String">
			<column name="NAME" length="20" not-null="true" />
		</property>
		<one-to-one name="wife" class="org.wpf.entity.Wife"
			cascade="all" property-ref="husband" />
	</class>
</hibernate-mapping>


Wife.hbm.xml

<?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 2018-1-22 22:47:11 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
	<class name="org.wpf.entity.Wife" table="WIFE">
		<id name="id" type="java.lang.Long">
			<column name="ID" />
			<generator class="native" />
		</id>
		<property name="name" type="java.lang.String">
			<column name="NAME" length="20" not-null="true" />
		</property>
		<many-to-one name="husband" class="org.wpf.entity.Husband"
			unique="true" column="husband_id" />
	</class>
</hibernate-mapping>

b.註解

Person

package org.wpf.entity;

import java.io.Serializable;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;

@Entity(name = "t1_person")
public class Person implements Serializable {
	private static final long serialVersionUID = -6446631496216328660L;

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;
	
	@Column(length = 32)
	private String name;
	
	@OneToOne(mappedBy = "person", cascade = CascadeType.ALL)
	private Card card;

	public Person() {
		super();
	}

	public Person(Long id, String name, Card card) {
		super();
		this.id = id;
		this.name = name;
		this.card = card;
	}

	public Long getId() {
		return id;
	}

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

	public String getName() {
		return name;
	}

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

	public Card getCard() {
		return card;
	}

	public void setCard(Card card) {
		this.card = card;
	}

}

Card

package org.wpf.entity;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;

@Entity(name = "t1_person")
public class Card implements Serializable {
	private static final long serialVersionUID = -5345063387498725762L;

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;

	@Column(length = 32)
	private String name;

	@OneToOne(optional = false)
	@JoinColumn(name = "person_id")
	private Person person;

	public Card() {
		super();
	}

	public Card(Long id, String name, Person person) {
		super();
		this.id = id;
		this.name = name;
		this.person = person;
	}

	public Long getId() {
		return id;
	}

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

	public String getName() {
		return name;
	}

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

	public Person getPerson() {
		return person;
	}

	public void setPerson(Person person) {
		this.person = person;
	}

}

12.多對多關聯

在關係型資料庫中是不能直接表達多對多關聯,必須引入一箇中間表
注意中間表表中不能包含非鍵列。中間表沒有對應的對映檔案


Student

package org.wpf.entity;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

public class Student implements Serializable {
	private static final long serialVersionUID = 7767264496828265124L;
	private Long id;
	private String name;
	private Set courses = new HashSet(0);

	public Student() {
		super();
	}

	public Student(Long id, String name, Set courses) {
		super();
		this.id = id;
		this.name = name;
		this.courses = courses;
	}

	public Long getId() {
		return id;
	}

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

	public String getName() {
		return name;
	}

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

	public Set getCourses() {
		return courses;
	}

	public void setCourses(Set courses) {
		this.courses = courses;
	}

}

Student.hbm.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
	<class name="org.wpf.entity.Student" table="t_student">
		<id name="id" type="java.lang.Long">
			<column name="ID" />
			<generator class="identity" />
		</id>
		<property name="name" type="java.lang.String">
			<column name="Name" length="20" not-null="true" />
		</property>
		<set name="courses" table="t_choice" cascade="all">
			<key>
				<column name="Student_id" not-null="true" />
			</key>
			<many-to-many entity-name="org.wpf.entity.Course">
				<column name="Course_id" not-null="true" />
			</many-to-many>
		</set>
	</class>
</hibernate-mapping>

Course

package org.wpf.entity;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

public class Course implements Serializable {
	private static final long serialVersionUID = -2850799906496654565L;
	private Long id;
	private String title;
	private Set students = new HashSet(0);

	public Course() {
		super();
	}

	public Course(Long id, String title, Set students) {
		super();
		this.id = id;
		this.title = title;
		this.students = students;
	}

	public Long getId() {
		return id;
	}

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

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public Set getStudents() {
		return students;
	}

	public void setStudents(Set students) {
		this.students = students;
	}

}

Course.hbm.xml

<?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 2018-1-22 23:00:29 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
    <class name="org.wpf.entity.Course" table="t_course">
        <id name="id" type="java.lang.Long">
            <column name="ID" />
            <generator class="native" />
        </id>
        <property name="title" type="java.lang.String">
            <column name="TITLE" length="50" not-null="true" />
        </property>
        <set name="students" inverse="true" table="t_choice">
            <key>
                <column name="Course_id" not-null="true" />
            </key>
           <many-to-many entity-name="org.wpf.entity.Student">
				<column name="Student_id" not-null="true" />
			</many-to-many>
        </set>
    </class>
</hibernate-mapping>
控制檯資訊
Hibernate: 
    
    create table t_choice (
       Course_id bigint not null,
        Student_id bigint not null,
        primary key (Student_id, Course_id)
    ) engine=InnoDB
Hibernate: 
    
    create table t_course (
       ID bigint not null auto_increment,
        TITLE varchar(50) not null,
        primary key (ID)
    ) engine=InnoDB
Hibernate: 
    
    create table t_student (
       ID bigint not null auto_increment,
        Name varchar(20) not null,
        primary key (ID)
    ) engine=InnoDB
Hibernate: 
    
    alter table t_choice 
       add constraint FK93ey2xm8fobois7ev90lrrefd 
       foreign key (Student_id) 
       references t_student (ID)
Hibernate: 
    
    alter table t_choice 
       add constraint FKjd0jtvxffqm4e7yi50ed1frju 
       foreign key (Course_id) 
       references t_course (ID)
檢視資料庫


13.Hibernate註解規範的文件中提供了三種方法

將元件類註解為@Embeddable,並將元件的屬性註解為@Id

public class UserRole implements Serializable {
	@EmbeddedId  private UserRolePK pk;
} 

將元件的屬性註解為@ EmbeddedId

@Embeddable 
public class UserId implements Serializable {
	@Id 
	UserId uid;
}
將類註解為@IdClass,並將該實體中所有主鍵屬性註解為@Id,最常用的方法

需要根據所有的主鍵屬性,建立一個主鍵類

主鍵類必須實現序列化介面(Serializable)

主鍵類必須有預設的public無引數的構造方法

主鍵類必須覆蓋equals和hashCode方法

@IdClass(IPMapKey.class)
public class IPMap {
	@Id @Column(name="IP") 
	private String ip; 
	@Id @Column(name="ExamPlaceId") 
	private String examPlaceId;   
}

相關推薦

JavaEE學習筆記Hibernate_06_註解開發getCurrentSession()對映關係

Hibernate_06 A.註解 1.概述 每個持久化POJO類都是一個實體Bean 通過在類的定義中使用@Entity註解來進行宣告 目前定義屬性對應的列時有兩種定義方法 a.定義在屬性上 b.定義在get方法上 兩種方法是等價的,目前沒有選擇標準,但一個類中

JAVAEE學習筆記hibernate03:多表操作級聯練習:添加聯系人

row tac 默認值 rac user except pro intra com 一、一對多|多對一 1、關系表達  表中的表達      實體中的表達      orm元數據中表達     一對多 <!-- 集合,一對多關系,在配置文件中配置 -

JavaEE學習筆記SpringMVC_01_快速搭建一個環境簡介常用方法

SpringMVC_01 A.快速搭建一個SpringMVC環境 1.搭建框架 <project xmlns="http://maven.apache.org/POM/4.0.0" xm

JavaEE學習筆記Spring_03_IoC的其他配置方式AOP淺析

Spring_03 A.IoC的其他配置方式 1.xml+Annotation bean package org.wpf.spr_01; import org.springframework

JAVAEE學習筆記hibernate02:實體規則、對象狀態、緩存、事務、批量查詢和實現客戶列表顯示

使用 ins tro trace ges create 綁定 criteria 命名 一、hibernate中的實體規則 實體類創建的註意事項  1.持久化類提供無參數構造  2.成員變量私有,提供共有get/set方法訪問.需提供屬性  3.持久化類中的屬性,應盡量使用包

JAVAEE學習筆記hibernate04:查詢種類、HQL、Criteria、查詢優化和練習為客戶列表增加查詢條件

沒有 arrays getpara tex response 寫法 sum exceptio 提高 一、查詢種類 1.oid查詢-get 2.對象屬性導航查詢 3.HQL 4.Criteria 5.原生SQL 二、查詢-HQL語法 //學習HQL語法 public

java學習筆記淺析JavaWeb開發中Model1模式和Model2模式

Model1模式   JavaBean就是java類,JavaBean分兩類:一類是實體Bean,一類是業務Bean model1模式優點:執行效率高,開發效率比較高,適合小型專案 model1模式缺點:邏輯比較混亂,頁面混亂,維護困難,擴充套件不容易   Model2模式

JavaEE學習筆記Hibernate_04_ORMHibernate主鍵策略,uuid

Hibernate_04 A.模式,層 1.模式與框架 a.模式 是專家總結出來,在某種情況下,解決某類問題的最佳解決方案 是思想、知識 b.框架 是一種半成品軟體,供開發者進行制定,達到簡化開發 是工具 2.四層架構 表現層:Struts2    Spr

JavaEE學習筆記Hibernate_03_快取機制自定義通用HibernateDAO工具類

Hibernate_03 A.Hibernate快取 1.一級快取 一級快取是Session快取,屬於事務範圍的快取,由hibernate管理的 只要應用程式通過Session介面來執行CRUD操作 Hibernate就會啟用一級快取,把資料庫中的資料以物件的形式拷貝

JavaEE學習筆記Spring_01_工廠模式Spring小程式IoC控制反轉

Spring_01 A.工廠模式 1.概述 是由專家總結出來的,在某種情況下解決某類問題的最佳解決方案 設計模式六大原則 單一職責原則 里氏替換原則 依賴倒置原則 介面隔離原則 迪米特法則 開

Spring學習筆記1:開發環境,BeanFactory和ApplicationContext兩類容器

開發環境 和Struts2,Hibernate一樣把下載的jar包放在WEB-INF/lib/下就可以了,最小依賴是: 其中commons-logging-*.jar是額外的,不是Spring自帶的。 BeanFactory容器 是為依賴注入(DI)

Git學習筆記刪除檔案及資料夾並push到遠端庫

本文講述如何把本地倉庫上的檔案或者資料夾刪除,並且將這些改動提交到遠端倉庫。 1、準備 建立一個檔案並提交到版本庫中: 現在我想把版本庫中的test.txt檔案刪除。 把這個檔案push到遠端倉庫orgin中。 執行:git push origin master 2、

Lua學習筆記 Lua中實現面向物件轉自雲風的部落格

local _class={} function class(super) local class_type={} class_type.ctor=false class_type.super=super class_type.new=function(...) local obj={}

微信小程式學習筆記1:開發一個帶歷史記錄功能的四則計算器

端午CSDN學院促銷,買了微信小程式開發實戰跟著學習一下。 混合模式移動應用 微信小程式是一種Hybrid-App(混合模式移動應用),它是介於Native-App和Web-App之間的,更接近前者,但開發成本小很多。 基本結構 pages目錄:其內的

webpack學習筆記a06-生產環境和開發環境配置

生產環境和開發環境的配置目標不一樣,生產環境主要是讓檔案壓縮得更小,更優化資源,改善載入時間。 而開發環境,主要是要開發更方便,更節省時間,比如除錯比如自動重新整理。 所以可以分開配置不同的開發環境,然後需要哪種用哪種。 配置流程實踐記錄: 新建專案資料夾 demo 初始化 npm ini

FRDM-KW41Z學習筆記FRDM-KW41Z開發板入門

本文主要介紹基於FRDM-KW41Z無線微控制器的MCU開發板。 FRDM-KW41Z開發板支援恩智浦KW41Z/31Z/21Z系列無線微控制器MCU。KW41Z控制器集成了一個2.36 GHz至2.48 GHz的無線電收發器(支援一系列FSK/GFSK和O-

CTP學習筆記CTP客戶端開發指南 學習筆記

1、組播行情        使用函式CreateFtdcMdApi 建立CThostFtdcMdApi 的例項。其中第一個引數是本地流檔案生成的目錄。流檔案是行情介面或交易介面在本地生成的流檔案,字尾名為.con。流檔案中記錄著客戶端收到的所有的資料流的數量。第二個引數描述

C#學習筆記Lesson5-串列埠除錯助手開發

學習有幾天時間了,跟著大神的指導和手冊以及萬能的度娘。下面記錄下串列埠除錯助手的開發,還並不是很完善,但是基本功能還是有的。一下就不一步步記錄開發過程了,貼上程式碼,以及重點和需要注意的地方。最終程式碼如下:using System; using System.Collect

Spring學習筆記11 spring aop 程式設計(註解方式)

2018.5.25註解方式比較繁瑣不直觀,瞭解即可1.建立web專案2.引入jar包在原來jar包基礎上引入aop相關的jar包3.日誌檔案log4j.properties4.準備目標物件先建立介面再建立實現類package com.lu.spring.aop.service

JAVAWEB學習筆記12_Http&Tomcat

請求重定向 san res tor tomcat啟動 zha rac pac b- 一、Http協議 1.什麽是Http協議 HTTP,超文本傳輸協議(HyperText Transfer Protocol)是互聯網上應用最為廣泛的 一種網絡協議。所有的WWW文