日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Hibernate【查询、连接池、逆向工程】

發布時間:2025/6/16 编程问答 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Hibernate【查询、连接池、逆向工程】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2019獨角獸企業重金招聘Python工程師標準>>>

前言

在Hibernate的第二篇中只是簡單地說了Hibernate的幾種查詢方式....到目前為止,我們都是使用一些簡單的主鍵查詢阿...使用HQL查詢所有的數據....本博文主要講解Hibernate的查詢操作,連接池,逆向工程的知識點...

get/load主鍵查詢

由于主鍵查詢這個方法用得比較多,于是Hibernate專門為我們封裝了起來...

  • get()立即查詢
  • load()懶加載

對象導航查詢

如果對象與對象之前存在一對多、多對一的關系的時候

  • 在以前SQL查詢的時候:我們如果想要得到當前對象與另一對象的關聯關系的時候,就必須用多表查詢來得到數據
  • Hibernate提供了對象導航查詢:我們可以使用主鍵查詢完之后,得到的對象,直接使用對象得到集合...就可以得到對應的數據了
// 對象導航查詢Dept dept = (Dept) session.get(Dept.class, 12);System.out.println(dept.getDeptName());//這里就可以得到部門對應的所有員工System.out.println(dept.getEmps());

HQL查詢

Hibernate的前面章節中已經講解過了基本的概念了。在這里我們就直接看看怎么使用了。

值得注意的是:

  • 在hbm.xml文件中的auto-import="true" 要設置true。當然了,默認值就是ture
  • 如果是false,寫hql的時候,要指定類的全名

查詢全部列

//方式一:直接寫對象Query q = session.createQuery("from Dept");//方式二:可以為對象取別名Query q = session.createQuery("select d from Dept d");

值得注意的是:HQL不支持*號,下面的代碼是錯誤的。

//不能用*Query q = session.createQuery("select * from Dept d");

查詢指定的列

值得注意的是:使用HQL查詢指定的列,返回的是對象數組Object[]

//只查詢name和eatBanana列Query query = session.createQuery("select m.name,m.eatBanana from Monkey m");System.out.println(query.list());

?

?

封裝對象

前面測試了查詢指定的列的時候,返回的是對象數組...可是對象數組我們不好操作啊...Hibernate還提供了將對象數組封裝成對象的功能

  • JavaBean要有對應的構造函數
Query query = session.createQuery("select new Monkey(m.name,m.eatBanana )from Monkey m");

條件查詢

在SQL中條件查詢我們也用得比較多,我們來看看HQL中的條件查詢有什么新特性。

占位符

占位符就是指?號,我們在SQL中也常常用...

Query query = session.createQuery("from Monkey m where m.name=?");//HQL是從0開始的query.setParameter(0, "大猴子");System.out.println(query.list());

?

?

命名參數

HQL還支持命名參數查詢!下面我們來看一下怎么用:

語法::命名

Query query = session.createQuery("from Monkey m where m.name=:monkeyName");//HQL是從0開始的query.setParameter("monkeyName", "大猴子");System.out.println(query.list());

?

?

范圍查詢

范圍查詢就是使用between and關鍵字來查詢特定范圍的數據。。和SQL是一樣的...

Query q = session.createQuery("from Dept d where deptId between ? and ?");q.setParameter(0, 1);q.setParameter(1, 20);System.out.println(q.list());

模糊查詢

模糊查詢就是使用Like關鍵字進行查詢,和SQL也是一樣的。

  • %號要寫在參數上,不能寫帶SQL上!
//模糊Query q = session.createQuery("from Dept d where deptName like ?");q.setString(0, "%部%");System.out.println(q.list());

聚合函數統計

我們也經常會查詢數據庫中一共有多少條記錄這樣的需求。那么在HQL中怎么用呢?

  • HQL提供了uniqueResult()這么一個方法,返回只有一條記錄的數據
Query query = session.createQuery("select COUNT(*) from Monkey");Object o = query.uniqueResult();System.out.println(o);

?

?

分組查詢

分組查詢和SQL是一樣的...

//-- 統計t_employee表中,每個部門的人數//數據庫寫法:SELECT dept_id,COUNT(*) FROM t_employee GROUP BY dept_id;// HQL寫法Query q = session.createQuery("select e.dept, count(*) from Employee e group by e.dept");System.out.println(q.list());

連接查詢

連接查詢也就是多表查詢...多表查詢有三種

  • 內連接【等值連接】
  • 左外連接
  • 有外鏈接

值得注意的是:連接查詢返回的也是對象數組!

//1) 內連接 【映射已經配置好了關系,關聯的時候,直接寫對象的屬性即可】Query q = session.createQuery("from Dept d inner join d.emps");//2) 左外連接Query q = session.createQuery("from Dept d left join d.emps");//3) 右外連接Query q = session.createQuery("from Employee e right join e.dept");q.list();

迫切連接

由于連接查詢返回的是對象數組,我們使用對象數組來操作的話會很不方便...既然是連接查詢,那么對象與對象是肯定有關聯關系的...于是乎,我們想把左表的數據填充到右表中,或者將右表的數據填充到左表中...使在返回的時候是一個對象、而不是對象數組!HQL提供了fetch關鍵字供我們做迫切連接

//1) 迫切內連接 【使用fetch, 會把右表的數據,填充到左表對象中!】Query q = session.createQuery("from Dept d inner join fetch d.emps");q.list();//2) 迫切左外連接Query q = session.createQuery("from Dept d left join fetch d.emps");q.list();

查詢語句放在配置文件中【命名查詢】

我們可以在具體的映射配置文件中存放一些常用的語句。以Dept為例

<!-- 存放sql語句,如果有<>這樣的字符數據,需要使用CDATA轉義! --><query name="getAllDept"><![CDATA[from Dept d where deptId < ?]]></query>

在程序中,我們可以獲取配置文件配置的語句

Query q = session.getNamedQuery("getAllDept");q.setParameter(0, 10);System.out.println(q.list());

Criteria 查詢

Criteria是一種完全面向對象的查詢...

Criteria使用的是add()來添加條件。條件又使用一個Restrictions類來封裝

Criteria criteria = session.createCriteria(Monkey.class);criteria.add(Restrictions.eq())

我們來簡單看一下Restrictions的方法:

?

?

都是一些大于、小于、等于之類的....Criteria查詢就使用不了分組、連接查詢了。

SQLQuery本地SQL查詢

有的時候,我們可能表的結構十分復雜,如果使用關聯映射的話,配置文件是十分臃腫的...因此,我們并不是把全部的數據表都使用映射的方式來創建數據表...

這時,我們就需要用到SQLQuery來維護我們的數據了..

SQLQuery是不能跨數據庫的,因為Hibernate在配置的時候就指定了數據庫的“方言”...

?

SQLQuery sqlQuery = session.createSQLQuery("SELECT * FROM monkey_ limit 0,3");System.out.println(sqlQuery.list());

返回的也是對象數組:

?

?

Hibernate也支持在SQLQuery中對數據進行對象封裝..只要添加類型就行了

SQLQuery sqlQuery = session.createSQLQuery("SELECT * FROM monkey_ limit 0,3").addEntity(Monkey.class);System.out.println(sqlQuery.list());

?

?

分頁查詢

傳統的SQL我們在DAO層中往往都是使用兩個步驟來實現分頁查詢

  • 得到數據庫表中的總記錄數
  • 查詢起始位置到末尾位數的數據

Hibernate對分頁查詢也有很好地支持,我們來一下:

Query query = session.createQuery("from Monkey");//得到滾動結果集ScrollableResults scroll = query.scroll();//滾動到最后一行scroll.last();int i = scroll.getRowNumber() + 1;System.out.println("總計路數:" + i);//設置分頁位置query.setFirstResult(0);query.setMaxResults(3);System.out.println(query.list());
  • 提供了方法讓我們設置起始位置和結束位置
  • 提供了ScrollableResults來得到滾動結果集,最終得到總記錄數

值得注意的是,滾動結果集是從0開始的,因此需要+1才可得到總記錄數!

?

?

如果我們們使用的是SELECT COUNT(*) FROM 實體,我們可以通過uniqueResult()方法獲取數據的唯一記錄,得到的數據轉換成Long類型即可。

Long totalRecord = (Long) queryCount.uniqueResult();

Hibernate連接池

Hibernate自帶了連接池,但是呢,該連接池比較簡單..而Hibernate又對C3P0這個連接池支持...因此我們來更換Hibernate連接池為C3P0

查看Hibernate自帶的連接池

我們可以通過Hibernate.properties文件中查看Hibernate默認配置的連接池

hibernate.properties的配置文件可以在\project\etc找到

Hibernate的自帶連接池啥都沒有,就一個連接數量為1...

?

?

查看Hibernate對C3P0的支持

  • #hibernate.c3p0.max_size 2 最大連接數
  • #hibernate.c3p0.min_size 2 最小連接數
  • #hibernate.c3p0.timeout 5000 超時時間
  • #hibernate.c3p0.max_statements 100 最大執行的命令的個數
  • #hibernate.c3p0.idle_test_period 3000 空閑測試時間
  • #hibernate.c3p0.acquire_increment 2 連接不夠用的時候, 每次增加的連接數
  • #hibernate.c3p0.validate false

?

?

修改Hibernate連接池

我們在hibernate.cfg.xml中配置C3p0,讓C30P0作為Hibernate的數據庫連接池

查找Hibernate支持的連接池組件有什么

?

?

既然找到了,那么我們在hibernate.cfg.xml中配置對應的類就和相關配置就行了

<!-- 【連接池配置】 --><!-- 配置連接驅動管理類 --><property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property><!-- 配置連接池參數信息 --><property name="hibernate.c3p0.min_size">2</property><property name="hibernate.c3p0.max_size">4</property><property name="hibernate.c3p0.timeout">5000</property><property name="hibernate.c3p0.max_statements">10</property><property name="hibernate.c3p0.idle_test_period">30000</property><property name="hibernate.c3p0.acquire_increment">2</property>

線程Session使用

我們創建Session的時候,有兩個方法

  • openSession()【每次都會創建新的Session】
  • getCurrentSession()【獲取當前線程的Session,如果沒有則創建】

一般地,我們使用線程Session比較多

如果要使用getCurrentSession(),需要在配置文件中配置:

<!--配置線程Session--><property name="hibernate.current_session_context_class">thread</property>

測試數據

@Testpublic void testSession() throws Exception {//openSession: 創建Session, 每次都會創建一個新的sessionSession session1 = sf.openSession();Session session2 = sf.openSession();System.out.println(session1 == session2);session1.close();session2.close();//getCurrentSession 創建或者獲取session// 線程的方式創建session // 一定要配置:<property name="hibernate.current_session_context_class">thread</property>Session session3 = sf.getCurrentSession();// 創建session,綁定到線程Session session4 = sf.getCurrentSession();// 從當前訪問線程獲取sessionSystem.out.println(session3 == session4);// 關閉 【以線程方式創建的session,可以不用關閉; 線程結束session自動關閉】//session3.close();//session4.close(); 報錯,因為同一個session已經關閉了!}

為什么要使用逆向工程

由于我們每次編寫Hibernate的時候都需要寫實體,寫映射文件。而且Hibernate的映射文件也容易出錯。而逆向工程可以幫我們自動生成實體和映射文件,這樣就非常方便了。

使用PowerDesigner

在設計數據庫表時,我們使用PowerDesigner來生成概念模型\物理模型...

設計一個人員組織架構:有機構、部門、員工、領導、角色、權限。

  • 一個機構有多個部門
  • 一個部門有多個員工
  • 領導可以管理多個部門,同時領導他自己也是員工
  • 一個員工可以有多個角色
  • 一個角色可以分配給多個人
  • 人員角色分配后可以設置是否有效,分配時間等
  • 一個角色有多個權限

概念模型:

?

?

在PowerDesigner中,箭頭指向的方向永遠是“一”的一方

生成物理模型:

?

?

?

?

最后生成物理模型是這樣子的:

?

?

生成sql語句

我們可以單個生成,一個一個復制

?

?

也可以把整個物理模型的sql語句一起生成:

?

?

/*==============================================================*//* DBMS name: MySQL 5.0 *//* Created on: 2017/6/5 20:22:52 *//*==============================================================*/drop table if exists person_role;drop table if exists t_company;drop table if exists t_dept;drop table if exists t_employee;drop table if exists t_person;drop table if exists t_privilege;drop table if exists t_role;drop table if exists t_role_privilege;/*==============================================================*//* Table: person_role *//*==============================================================*/create table person_role(person_id varchar(32) not null,role_id varchar(32) not null,state varchar(32),primary key (person_id, role_id));/*==============================================================*//* Table: t_company *//*==============================================================*/create table t_company(company_id varchar(32) not null,name varchar(32),primary key (company_id));/*==============================================================*//* Table: t_dept *//*==============================================================*/create table t_dept(dept_id varchar(32) not null,company_id varchar(32) not null,name varchar(32),primary key (dept_id));/*==============================================================*//* Table: t_employee *//*==============================================================*/create table t_employee(person_id varchar(32) not null,dept_id varchar(32),name varchar(32),employee_id varchar(32),primary key (person_id));/*==============================================================*//* Table: t_person *//*==============================================================*/create table t_person(person_id varchar(32) not null,dept_id varchar(32) not null,name varchar(32),primary key (person_id));/*==============================================================*//* Table: t_privilege *//*==============================================================*/create table t_privilege(privilege_id varchar(32) not null,name varchar(32),primary key (privilege_id));/*==============================================================*//* Table: t_role *//*==============================================================*/create table t_role(role_id varchar(32) not null,name varchar(32),primary key (role_id));/*==============================================================*//* Table: t_role_privilege *//*==============================================================*/create table t_role_privilege(role_id varchar(32) not null,privilege_id varchar(32) not null,primary key (role_id, privilege_id));alter table person_role add constraint FK_person_role foreign key (person_id)references t_person (person_id) on delete restrict on update restrict;alter table person_role add constraint FK_person_role2 foreign key (role_id)references t_role (role_id) on delete restrict on update restrict;alter table t_dept add constraint FK_companty_dept foreign key (company_id)references t_company (company_id) on delete restrict on update restrict;alter table t_employee add constraint FK_inherit foreign key (person_id)references t_person (person_id) on delete restrict on update restrict;alter table t_person add constraint FK_dept_person foreign key (dept_id)references t_dept (dept_id) on delete restrict on update restrict;alter table t_role_privilege add constraint FK_belong foreign key (role_id)references t_role (role_id) on delete restrict on update restrict;alter table t_role_privilege add constraint FK_own foreign key (privilege_id)references t_privilege (privilege_id) on delete restrict on update restrict;

在數據庫生成八張表:

?

?

在Idea下使用Hibernate逆向工程

?

?

值得注意的是:Intellij idea下生成出來的映射文件是沒有對應的關聯關系的。也就是說:一對多或多對多的關系,它是不會幫你自動生成的【好像是這樣子的】。。。因此,需要我們自己添加Set【如果需要】

更新,如果想要體現對應的關聯關系的話,請參考該博文!

  • https://my.oschina.net/wangyuefive/blog/683771

如果文章有錯的地方歡迎指正,大家互相交流。習慣在微信看技術文章,想要獲取更多的Java資源的同學,可以關注微信公眾號:Java3y

?

?

轉載于:https://my.oschina.net/u/3777556/blog/1631982

總結

以上是生活随笔為你收集整理的Hibernate【查询、连接池、逆向工程】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。