需要導入的hibernate的包 其中所需要的依賴包 需要的配置文件 一個是元數據orm的配置文件 例如 當前一個Customer對象 需要建立他相應的xml文件 接下啦是hibernate的主配置文件最重要的該文件的文件名字必須是hibernate.cfg.xml,同時在src的目錄 代碼的增刪改 ...
需要導入的hibernate的包
其中所需要的依賴包
需要的配置文件
一個是元數據orm的配置文件
例如
package com.fmt.hibernate;public class Customer {
/*
* CREATE TABLE `cst_customer` (
`cust_id` BIGINT(32) NOT NULL AUTO_INCREMENT COMMENT '客戶編號(主鍵)',
`cust_name` VARCHAR(32) NOT NULL COMMENT '客戶名稱(公司名稱)',
`cust_source` VARCHAR(32) DEFAULT NULL COMMENT '客戶信息來源',
`cust_industry` VARCHAR(32) DEFAULT NULL COMMENT '客戶所屬行業',
`cust_level` VARCHAR(32) DEFAULT NULL COMMENT '客戶級別',
`cust_linkman` VARCHAR(64) DEFAULT NULL COMMENT '聯繫人',
`cust_phone` VARCHAR(64) DEFAULT NULL COMMENT '固定電話',
`cust_mobile` VARCHAR(16) DEFAULT NULL COMMENT '行動電話',
PRIMARY KEY (`cust_id`)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
*/
private Long cust_id; private String cust_name; private String cust_source; private String cust_industry; private String cust_level; private String cust_linkman; private String cust_phone; private String cust_mobile; public Long getCust_id() { return cust_id;
} public void setCust_id(Long cust_id) { this.cust_id = cust_id;
} public String getCust_name() { return cust_name;
} public void setCust_name(String cust_name) { this.cust_name = cust_name;
} public String getCust_source() { return cust_source;
} public void setCust_source(String cust_source) { this.cust_source = cust_source;
} public String getCust_industry() { return cust_industry;
} public void setCust_industry(String cust_industry) { this.cust_industry = cust_industry;
} public String getCust_level() { return cust_level;
} public void setCust_level(String cust_level) { this.cust_level = cust_level;
} public String getCust_linkman() { return cust_linkman;
} public void setCust_linkman(String cust_linkman) { this.cust_linkman = cust_linkman;
} public String getCust_phone() { return cust_phone;
} public void setCust_phone(String cust_phone) { this.cust_phone = cust_phone;
} public String getCust_mobile() { return cust_mobile;
} public void setCust_mobile(String cust_mobile) { this.cust_mobile = cust_mobile;
} @Override
public String toString() { return "Customer [cust_id=" + cust_id + ", cust_name=" + cust_name + "]";
}
}
當前一個Customer對象 需要建立他相應的xml文件
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><!-- 配置與表實體對象的關係--><!-- package屬性,填寫一個包名.在元素內部凡是需要書寫完整類名的書寫,可以直接寫--><hibernate-mapping package="com.fmt.hibernate">
<!--
class元素:配置實體與表的對應關係
name:完整類名
table:表名
-->
<class name="Customer" table="cst_customer">
<!-- id:配置主鍵映射
name:填寫主鍵對應屬性名
column:填寫表中的主鍵列明
-->
<id name="cust_id" column="cust_id">
<!-- 主鍵生成策略-->
<generator class="native"></generator>
</id>
<!--property 除id之外的普通屬性映射
name:屬性名
column(可選):填寫;列名預設值是屬性名
type(可選) 填寫屬性的類型。hibernate會自動檢測試題的屬性類型
每個類型有三種添發:java類型|hibernate類型|資料庫類型
not-null(可選):配置該屬性(列)不為空,預設值為false
length(可選):配置資料庫中列的長度,預設值;當前資料庫中的最大長度
-->
<property name="cust_name" column="cust_name" not-null="true">
<!--<column name="cust_name" sql-type="varchar"></column>-->
</property>
<property name="cust_source" column="cust_source"></property>
<property name="cust_industry" column="cust_industry"></property>
<property name="cust_level" column="cust_level"></property>
<property name="cust_linkman" column="cust_linkman"></property>
<property name="cust_phone" column="cust_phone"></property>
<property name="cust_mobile" column="cust_mobile"></property>
</class></hibernate-mapping>
接下啦是hibernate的主配置文件最重要的該文件的文件名字必須是hibernate.cfg.xml,同時在src的目錄
<?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主配置文件--><hibernate-configuration>
<session-factory>
<!--五個必選配置
hibernate.connection.driver_class:驅動
hibernate.connection.url:資料庫url
hibernate.connection.username:用戶名
hibernate.connection.password:用戶名密碼
hibernate.dialect:資料庫方言
不同資料庫中的,sql語法略有不同,指定方言可以讓hibernate框架在生成sql語句時,針對資料庫的方言生成
sql99標準:DDL/DML/DCL
-->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql:///hibernate?useUnicode=true&characterEncoding=utf8</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">123456</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- hibernate 顯示sql語句然後格式化sql-->
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<!--
##auto schema export 自動導出表結構,自動建表
hibernate.hbm2ddl.auto create 自動建表,每次框架運行都會建立新的表,以前的表將會被覆蓋,表數據會丟失(開發測試使用)
hibernate.hbm2ddl.auto create-drop 自動建表,每次框架運行都會將表刪除(開發環境測試還用)
hibernate.hbm2ddl.auto update (推薦使用) 自動生成表,如果存在不會再生成,如果表有變動,自動更新表(不會生成任何數據)
hibernate.hbm2ddl.auto validate 校驗不主動生成表,每次啟動會校驗資料庫中表是否正確,校驗失敗拋出異常(舉例刪除了表就會有異常)
-->
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 引入orm元數據 填寫src路徑下-->
<mapping resource="com/fmt/hibernate/Customer.cfg.xml"/>
</session-factory></hibernate-configuration>
代碼的增刪改查
@Test
public void fun1(){ //1創建,調用空參構造
Configuration conf=new Configuration(); //2讀取配置文件,j載入src下的Hibernate.cfg.xml文件
conf.configure(); //根據配置,創建SessionFactory對象
//SessionFaction就是用來創建Session的
//sessionFactory 負責保存和使用所有配置信息,消耗記憶體資源較大
//sessionFactory 屬於線程安全的對象設計
//所以SessionnFactory全局唯一
SessionFactory sessionFactory = conf.buildSessionFactory(); //session對象是表達hibernate框架與資料庫之間的連接可以理解為JDBC中的connection對象,但同時可以操作sql,是hibernate的核心對象
//獲取Session
Session session = sessionFactory.openSession(); //獲取線程綁定的session// Session currentSession = sessionFactory.getCurrentSession();
//獲取操作事務// Transaction transaction = session.getTransaction();
//開啟事務病獲得操作事務(建議使用)
Transaction transaction1 = session.beginTransaction(); /*
保存
Customer customer=new Customer();
customer.setCust_name("jd");
session.save(customer);
*/
/*
查詢
session.get 第一個參數是類,第二個是主鍵id
Customer customer = session.get(Customer.class, 1l);
System.out.println(customer);
*/
/*
修改
Customer customer = session.get(Customer.class, 1l);
customer.setCust_name("百度");
session.update(customer);
*/
/*
刪除
Customer customer = session.get(Customer.class, 1l);
customer.setCust_name("百度");
session.delete(customer);
*/
transaction1.commit();//提交// transaction1.rollback();//回滾
session.close();//釋放資源
sessionFactory.close();//釋放資源
}
實體類創建註意事項
-
持久化提供無參構造
-
成員變數私有,提供共有get/set方法訪問,需提供屬性
-
持久化類的屬性,應儘量使用包裝類型
-
持久化需要提供oid,與資料庫中的主鍵列對應(如果一個表沒有主鍵,無法映射到hibernate表中,主鍵相同hibernate認為對象相同)
-
不要用final修飾class(hibernate使用cglib代理生成代理對象,代理對象是繼承被代理對象,如果被final修改將無法生成代理)
主鍵生成策略
在元對象xml中
<class name="Customer" table="cst_customer">
<!-- id:配置主鍵映射
name:填寫主鍵對應屬性名
column:填寫表中的主鍵列明
-->
<id name="cust_id" column="cust_id">
<!-- 主鍵生成策略:主鍵生成策略,就是每條記錄錄入時,主鍵的生成規則
identity:主鍵自增,又資料庫來維護主鍵值,錄入時不需要指定主鍵
increment:主鍵自增,由hibernate來維護,每次插入前會先查詢表中id最大值加+1最為先主鍵(存線上程安全問題)
sequence:Oracle中的主鍵生成策略
hilo:高低位演算法,主鍵自增,由hibernate來維護,開發不使用
native:hilo+sequence+identity ,三選一策略。如果自持主鍵自增就使用identity 如果支持Oracle則使用sequence...
uuid:產生隨機字元串,主鍵類型必須是string類型
assigned:自然主鍵生成策略,hibernate不會管理主鍵值,由開發人員自己錄入,如果不設置id 就會報錯
-->
<generator class="native"></generator>
</id>
.....
hibernate實體對象的狀態
三種狀態:瞬時狀態,持久化狀態,游離狀態
Configuration conf=new Configuration();
conf.configure();
SessionFactory sessionFactory = conf.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
Customer customer=new Customer();//沒有id,沒有與session關聯
customer.setCust_name("jd");//瞬時狀態
session.save(customer);//持久化狀態,由id,有關聯
transaction.commit();//提交
session.close();//游離|托管狀態。有id。沒關聯
sessionFactory.close();
持久化狀態的特點持久化對象的任何變化都會自動同步到資料庫中
Configuration conf=new Configuration();
conf.configure();
SessionFactory sessionFactory = conf.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
Customer customer = session.get(Customer.class, 2l);
customer.setCust_name("tianmao");//這裡沒有設置update的操作,仍然修改了資料庫
transaction.commit();//提交
session.close();
sessionFactory.close();
hibernate一級緩存
Test
public void fun1() {
Configuration conf = new Configuration().configure();
SessionFactory sessionFactory = conf.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
//這裡這回進行一次的查詢 session緩存了 id位2l的custion到記憶體中,第二次查詢不會走資料庫查詢
Customer customer1 = session.get(Customer.class, 2l);
Customer customer2 = session.get(Customer.class, 2l);
Customer customer3 = session.get(Customer.class, 2l);
System.out.println(customer1==customer2);
transaction.commit();
session.close();
sessionFactory.close();
}
@Test
public void fun2() {
Configuration conf = new Configuration().configure();
SessionFactory sessionFactory = conf.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
Customer customer1 = session.get(Customer.class, 2l);//tianmao
customer1.setCust_name("jd");
customer1.setCust_name("tianmao");
//這裡不會進行update操作,值進行了查詢的sql
//seesion保存了查詢出來後的快照,對比當時的快照是否發生變化同步到資料庫
transaction.commit();
session.close();
sessionFactory.close();
}
Hibernate的隔離級別設置
在主配置文件中
加入<!--指定hibernate操作資料庫的隔離級別
1|2|4|8
1 讀未提交(臟讀,不可重覆讀,幻|虛讀)
2 讀已提交(不可重覆讀,幻|虛讀)
4 課重覆讀(幻|虛讀)
8 串列化(沒有問題 但是效率太低)
--><property name="hibernate.connection.isolation">4</property>
調用獲取當前線程中的session對象調用sessionFactory.getCurrentSession(); 註意點需要在配置文件中聲明,同時通過getCurrentSession方法獲得到的session當事務提交時,session會自動關閉,不要手動close關閉
<!-- 指定session與當前線程綁定-->
<property name="hibernate.current_session_context_class">thread</property>
Hql查詢
hql查詢:HQL是Hibernate Query Language的簡寫,HQL採用面向對象的查詢方式
Session session= HibernateUtils.openSession();
Transaction transaction = session.beginTransaction(); //書寫HQL語句// String hql="from com.fmt.hibernate.Customer";// String hql="from Customer ";//查詢所有Custom對象
/**
//查詢id位2的
String hql="from Customer where cust_id =2";
Query query = session.createQuery(hql);
*/
/**
條件查詢
String hql="from Customer where cust_id =?";
Query query = session.createQuery(hql);
//query.setLong(0,2l);
query.setParameter(0,2l);//這個不用的參數做具體設置較為方便
*/
/**
命名查詢
String hql="from Customer where cust_id =:cust_id";//冒號後面的字元串是setParamerter中的第一個參數
Query query = session.createQuery(hql);
query.setParameter("cust_id",2l);
*/
/**
分頁查詢
String hql="from Customer ";
Query query = session.createQuery(hql);
query.setFirstResult(1);//第幾頁
query.setMaxResults(3);//每次返回最大多少
*/
List<Customer> list = query.list();//返回list
System.out.print(list);// Object o = query.uniqueResult();//接受唯一的查詢
//根據HQL語句創建查詢對象
//根據查詢對象獲取查詢結果
/**
//內鏈接
// String hql="from Customer c inner join c.linkMens";
// Query query = session.createQuery(hql);
// List<Object[]> list = query.list();
// for (Object[] arr:list){
// System.out.println(Arrays.toString(arr));
// }
//迫切內鏈接(與上述多了個fetch,同時query.list返回返現不在是Object[]),同理左外右外
// String hql="from Customer c inner join fetch c.linkMens";
// Query query = session.createQuery(hql);
// List<Customer> list = query.list();
// for (Customer arr:list){
// System.out.println(arr);
// }
*/
transaction.commit();
session.close();
Criteria查詢
Criteria是一種比hql更面向對象的查詢方式。Criteria 可使用 Criterion 和 Projection 設置查詢條件
Session session= HibernateUtils.openSession();
Transaction transaction = session.beginTransaction(); /**
基本查詢
Criteria criteria = session.createCriteria(Customer.class);
List<Customer> list = criteria.list();
*/
/**
* 條件查詢
* HQL中,不可能出現任何資料庫相關的信息
* > gt
* >= ge
* < lt
* <= le
* == eq
* != ne
* in in
* between and between
* like like
* is not null isNotNull
* is null isNull
* or or
* and and
//查詢所有Customer
Criteria criteria = session.createCriteria(Customer.class);
criteria.add(Restrictions.ne("cust_id",2l));//這裡的ne就是Resctirction提供的方法
List<Customer> list = criteria.list();
*/
/**
分頁
Criteria criteria = session.createCriteria(Customer.class);
criteria.setFirstResult(0);
criteria.setMaxResults(2);
List<Customer> list = criteria.list();
*/
/**
聚合函數
Criteria criteria = session.createCriteria(Customer.class);
criteria.setProjection(Projections.rowCount());//Projections
Long number = (Long) criteria.uniqueResult();
*/
System.out.println(list); /**
transaction.commit();
session.close();
//離線查詢 @Test
public void fun5(){
//上層構建查詢條件
DetachedCriteria dc=DetachedCriteria.forClass(Customer.class);
dc.add(Restrictions.idEq(61));
//dao層代碼基本不動
Session session= HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Criteria executableCriteria = dc.getExecutableCriteria(session);
List list = executableCriteria.list();
System.out.print(list);
transaction.commit();
session.close();
}
原生sql查詢
Session session= HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
String sql="select * from cst_customer";
SQLQuery sqlQuery = session.createSQLQuery(sql);
//因為查詢查來的是有幾行幾行裡面有幾列
List<Object[]> list = sqlQuery.list();
for (Object[] objs:list){
for (Object o:objs){
System.out.println(o);
}
}
transaction.commit();
session.close();
Session session= HibernateUtils.openSession();
Transaction transaction = session.beginTransaction(); /**
條件查詢
String sql="select * from cst_customer where cust_id =?";
SQLQuery sqlQuery = session.createSQLQuery(sql);
sqlQuery.setParameter(0,2l);
*/
/**
分頁查詢
String sql="select * from cst_customer limit ?,?";
SQLQuery sqlQuery = session.createSQLQuery(sql);
sqlQuery.setParameter(0,0);
sqlQuery.setParameter(1,1);
*/
//這裡是給添加實體,查詢後就會出該實體
sqlQuery.addEntity(Customer.class);
List list = sqlQuery.list();
System.out.print(list);
懶載入
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction(); /**
//立即獲得
Customer customer = session.get(Customer.class, 18l);
*/
/**
//返回一個代理對象 只有對對象使用了才會進行查詢
Customer customer = session.load(Customer.class, 18l);
System.out.println(customer);//這裡才會進行查詢如果不操作對象,最後也不會進行數據查詢
*/
//返回一個代理對象 如果當期對象唄使用了才會進行查詢
Customer customer = session.load(Customer.class, 18l);
transaction.commit();
session.close();
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
如果要關閉懶載入,建議是開啟懶載入
在對象的xml表中配置
//lazy 是關閉懶載入這樣load也是當即查詢,預設是true
<class name="Customer" table="cst_customer" lazy="false">
懶載入註意事項,在懶載入的使用要調用懶載入出來的對象,確保seesion並未關閉!!
一對多,多對一
public classCustomer { /*
* CREATE TABLE `cst_customer` (
`cust_id` BIGINT(32) NOT NULL AUTO_INCREMENT COMMENT '客戶編號(主鍵)',
`cust_name` VARCHAR(32) NOT NULL COMMENT '客戶名稱(公司名稱)',
`cust_source` VARCHAR(32) DEFAULT NULL COMMENT '客戶信息來源',
`cust_industry` VARCHAR(32) DEFAULT NULL COMMENT '客戶所屬行業',
`cust_level` VARCHAR(32) DEFAULT NULL COMMENT '客戶級別',
`cust_linkman` VARCHAR(64) DEFAULT NULL COMMENT '聯繫人',
`cust_phone` VARCHAR(64) DEFAULT NULL COMMENT '固定電話',
`cust_mobile` VARCHAR(16) DEFAULT NULL COMMENT '行動電話',
PRIMARY KEY (`cust_id`)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
*/
private Long cust_id; private String cust_name; private String cust_source; private String cust_industry; private String cust_level; private String cust_linkman; private String cust_phone; private String cust_mobile; private Set<LinkMan> linkMens=new HashSet<>(); public Long getCust_id() { return cust_id;
} public void setCust_id(Long cust_id) { this.cust_id = cust_id;
} public String getCust_name() { return cust_name;
} public void setCust_name(String cust_name) { this.cust_name = cust_name;
} public String getCust_source() { return cust_source;
} public void setCust_source(String cust_source) { this.cust_source = cust_source;
} public String getCust_industry() { return cust_industry;
} public void setCust_industry(String cust_industry) { this.cust_industry = cust_industry;
} public String getCust_level() { return cust_level;
} public void setCust_level(String cust_level) { this.cust_level = cust_level;
} public String getCust_linkman() { return cust_linkman;
} public void setCust_linkman(String cust_linkman) { this.cust_linkman = cust_linkman;
} public String getCust_phone() { return cust_phone;
} public void setCust_phone(String cust_phone) { this.cust_phone = cust_phone;
} public String getCust_mobile() { return cust_mobile;
} public void setCust_mobile(String cust_mobile) { this.cust_mobile = cust_mobile;
} public Set<LinkMan> getLinkMens() { return linkMens;
} public void setLinkMens(Set<LinkMan> linkMens) { this.linkMens = linkMens;
}
@Override public String toString() { return "Customer [cust_id=" + cust_id + ", cust_name=" + cust_name + "]";
}
}//聯繫人實體public class LinkMan { /*
* CREATE TABLE `cst_linkman` (
`lkm_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '聯繫人編號(主鍵)',
`lkm_name` varchar(16) DEFAULT NULL COMMENT '聯繫人姓名',
`lkm_cust_id` bigint(32) NOT NULL COMMENT '客戶id',
`lkm_gender` char(1) DEFAULT NULL COMMENT '聯繫人性別',
`lkm_phone` varchar(16) DEFAULT NULL COMMENT '聯繫人辦公電話',
`lkm_mobile` varchar(16) DEFAULT NULL COMMENT '聯繫人手機',
`lkm_email` varchar(64) DEFAULT NULL COMMENT '聯繫人郵箱',
`lkm_qq` varchar(16) DEFAULT NULL COMMENT '聯繫人qq',
`lkm_position` varchar(16) DEFAULT NULL COMMENT '聯繫人職位',
`lkm_memo` varchar(512) DEFAULT NULL COMMENT '聯繫人備註',
PRIMARY KEY (`lkm_id`),
KEY `FK_cst_linkman_lkm_cust_id` (`lkm_cust_id`),
CONSTRAINT `FK_cst_linkman_lkm_cust_id` FOREIGN KEY (`lkm_cust_id`) REFERENCES `cst_customer` (`cust_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
*/
private Long lkm_id; private Character lkm_gender; private String lkm_name; private String lkm_phone; private String lkm_email; private String lkm_qq; private String lkm_mobile; private String lkm_memo; private String lkm_position; //表達多對一關係
private Customer customer ; //----------------------------------------------
//不與資料庫中的列對應,只為了接收表單參數
private Long cust_id; public Long getCust_id() { return cust_id;
} public void setCust_id(Long cust_id) { this.cust_id = cust_id;
} public Customer getCustomer() { return customer;
} public void setCustomer(Customer customer) { this.customer = customer;
} public Long getLkm_id() { return lkm_id;
} public void setLkm_id(Long lkm_id) { this.lkm_id = lkm_id;
} public Character getLkm_gender() { return lkm_gender;
} public void setLkm_gender(Character lkm_gender) { this.lkm_gender = lkm_gender;
} public String getLkm_name() { return lkm_name;
} public void setLkm_name(String lkm_name) { this.lkm_name = lkm_name;
} public String getLkm_phone() { return lkm_phone;
} public void setLkm_phone(String lkm_phone) { this.lkm_phone = lkm_phone;
} public String getLkm_email() { return lkm_email;
} public void setLkm_email(String lkm_email) { this.lkm_email = lkm_email;
} public String getLkm_qq() { return lkm_qq;
} public void setLkm_qq(String lkm_qq) { this.lkm_qq = lkm_qq;
} public String getLkm_mobile() { return lkm_mobile;
} public void setLkm_mobile(String lkm_mobile) { this.lkm_mobile = lkm_mobile;
} public String getLkm_memo() { return lkm_memo;
} public void setLkm_memo(String lkm_memo) { this.lkm_memo = lkm_memo;
} public String getLkm_position() { return lkm_position;
} public void setLkm_position(String lkm_position) { this.lkm_position = lkm_position;
}
}
在原先的hibernate.cfg.xml
在添加 <mapping resource="com/fmt/hibernate/LinkMan.cfg.xml"/>修改原先的Customer.cfg.xml
添加一對多的的配置 <!--集合,一對多關係,在配置文件中配置-->
<!--
name是添集合屬性名
key元素 中column 填寫外鍵列名
class屬性 與我關聯的對象完整類名
-->
<!--
級聯操作:cascade
save-update:級聯保存更新
delete:級聯刪除
all上述都有
-->
<set name="linkMens" cascade="save-update">
<!--指定外鍵列明-->
<key column="lkm_cust_id"></key>
<one-to-many class="LinkMan"/>
</set>
同時配置LinkMan.cfg.xml
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping package="com.fmt.hibernate">
<class name="LinkMan" table="cst_linkman" >
<id name="lkm_id" >
<generator class="native"></generator>
</id>
<property name="lkm_gender" ></property>
<property name="lkm_name" ></property>
<property name="lkm_phone" ></property>
<property name="lkm_email" ></property>
<property name="lkm_qq" ></property>
<property name="lkm_mobile" ></property>
<property name="lkm_memo" ></property>
<property name="lkm_position" ></property>
<!-- 多對1關係-->
<many-to-one name="customer" column="lkm_cust_id" class="Customer" cascade="save-update" >
</many-to-one>
</class></hibernate-mapping>
@Test
public void fun1(){
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Customer customer = new Customer();
customer.setCust_name("阿裡");
LinkMan linkMan=new LinkMan();
linkMan.setLkm_name("馬雲1");
LinkMan linkMan1=new LinkMan();
linkMan1.setLkm_name("馬雲2");
customer.getLinkMens().add(linkMan);
customer.getLinkMens().add(linkMan1); /**
session.save(customer);
//這裡沒有添加保存linman對象是因為使用級聯操作,在之前Customer的配置中,級聯操作會順帶保存
// session.save(linkMan);
// session.save(linkMan1);
*/
/**
Customer customer = session.get(Customer.class, 18l);
LinkMan linkMan = new LinkMan();
linkMan.setLkm_name("馬雲3");
customer.getLinkMens().add(linkMan);
*/
/**
Customer customer = session.get(Customer.class, 18l);
LinkMan linkMan = session.get(LinkMan.class, 9l);
customer.getLinkMens().remove(linkMan);
//如果不調用delete 在資料庫id為9的linman還存在,但是指向Customer外鍵為null
//session.delete(linkMan);
如果需要刪除customer 同時刪除linkman 在linkman的配置文件中也添加級聯操作
*/
transaction.commit();
session.close();
}
Inverse 屬性
http://blog.csdn.net/lzgs_4/article/details/45844045(這篇講的比較通俗易懂)
多對多操作
//角色對象public class Role { /*
*
CREATE TABLE `sys_role` (
`role_id` bigint(32) NOT NULL AUTO_INCREMENT,
`role_name` varchar(32) NOT NULL COMMENT '角色名稱',
`role_memo` varchar(128) DEFAULT NULL COMMENT '備註',
PRIMARY KEY (`role_id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
*/
private Long role_id; private String role_name; private String role_memo; //表達多對多
private Set<User> users = new HashSet<User>(); public Long getRole_id() { return role_id;
} public void setRole_id(Long role_id) { this.role_id = role_id;
} public String getRole_name() { return role_name;
} public void setRole_name(String role_name) { this.role_name = role_name;
} public String getRole_memo() { return role_memo;
} public void setRole_memo(String role_memo) { this.role_memo = role_memo;
} public Set<User> getUsers() { return users;
} public void setUsers(Set<User> users) { this.users = users;
}
}public class User { /*
* CREATE TABLE `sys_user` (
`user_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '用戶id',
`user_code` varchar(32) NOT NULL COMMENT '用戶賬號',
`user_name` varchar(64) NOT NULL COMMENT '用戶名稱',
`user_password` varchar(32) NOT NULL COMMENT '用戶密碼',
`user_state` char(1) NOT NULL COMMENT '1:正常,0:暫停',
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;
*/
private Long user_id; private String user_code; private String user_name; private String user_password; private Character user_state; //表達多對多
private Set<Role> roles = new HashSet<Role>(); public Long getUser_id() { return user_id;
} public void setUser_id(Long user_id) { this.user_id = user_id;
} public String getUser_code() { return user_code;
} public void setUser_code(String user_code) { this.user_code = user_code;
} public String getUser_name() { return user_name;
} public void setUser_name(String user_name) { this.user_name = user_name;
} public String getUser_password() { return user_password;
} public void setUser_password(String user_password) { this.user_password = user_password;
} public Character getUser_state() { return user_state;
} public void setUser_state(Character user_state) { this.user_state = user_state;
} public Set<Role> getRoles() { return roles;
} public void setRoles(Set<Role> roles) { this.roles = roles;
}
}
User和Role的配置文件里 set內容是幾乎是鏡像的
在User的配置文件中配置 <!-- 多對多關係表達
name:集合屬性名
table:配置中間表名
key
-column:外鍵,別人引用“我的”外鍵
class:我與那個類是多對多關係
column:外鍵,我引用別人的外鍵列明
--><set name="roles" table="sys_user_role" cascade="save-update">
<key column="user_id"></key>
<many-to-many class="Role" column="role_id"></many-to-many>
</set>在Role的配置文件中配置 <!-- 使用inverse屬性
true:放棄維護外鍵關係
結論:將來在開發中,如果遇到多對多關係,一定要選擇一方放棄關係
一般誰來放棄看業務方向,例如錄入員工時,需要為員工指定所屬角色,
那麼業務方向就是由員工維護,角色不需要維護員工-->
<set name="users" table="sys_user_role" inverse="true">
<key column="role_id"></key>
<many-to-many class="User" column="user_id"></many-to-many>
</set>
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction(); /**
如果不設置inverse屬性會報錯查看上面配置
User u1=new User();
u1.setUser_name("小明");
User u2=new User();
u2.setUser_name("小紅");
Role r1=new Role();
r1.setRole_name("保潔");
Role r2=new Role();
r2.setRole_name("教師");
//用戶表達關係
u1.getRoles().add(r1);
u1.