Hibernate【查询、连接池、逆向工程】
2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>
前言
在Hibernate的第二篇中只是簡(jiǎn)單地說(shuō)了Hibernate的幾種查詢(xún)方式....到目前為止,我們都是使用一些簡(jiǎn)單的主鍵查詢(xún)阿...使用HQL查詢(xún)所有的數(shù)據(jù)....本博文主要講解Hibernate的查詢(xún)操作,連接池,逆向工程的知識(shí)點(diǎn)...
get/load主鍵查詢(xún)
由于主鍵查詢(xún)這個(gè)方法用得比較多,于是Hibernate專(zhuān)門(mén)為我們封裝了起來(lái)...
- get()立即查詢(xún)
- load()懶加載
對(duì)象導(dǎo)航查詢(xún)
如果對(duì)象與對(duì)象之前存在一對(duì)多、多對(duì)一的關(guān)系的時(shí)候
- 在以前SQL查詢(xún)的時(shí)候:我們?nèi)绻?strong>想要得到當(dāng)前對(duì)象與另一對(duì)象的關(guān)聯(lián)關(guān)系的時(shí)候,就必須用多表查詢(xún)來(lái)得到數(shù)據(jù)
- Hibernate提供了對(duì)象導(dǎo)航查詢(xún):我們可以使用主鍵查詢(xún)完之后,得到的對(duì)象,直接使用對(duì)象得到集合...就可以得到對(duì)應(yīng)的數(shù)據(jù)了。
HQL查詢(xún)
在Hibernate的前面章節(jié)中已經(jīng)講解過(guò)了基本的概念了。在這里我們就直接看看怎么使用了。
值得注意的是:
- 在hbm.xml文件中的auto-import="true" 要設(shè)置true。當(dāng)然了,默認(rèn)值就是ture
- 如果是false,寫(xiě)hql的時(shí)候,要指定類(lèi)的全名
查詢(xún)?nèi)苛?/h2> //方式一:直接寫(xiě)對(duì)象Query q = session.createQuery("from Dept");//方式二:可以為對(duì)象取別名Query q = session.createQuery("select d from Dept d");
值得注意的是:HQL不支持*號(hào),下面的代碼是錯(cuò)誤的。
//不能用*Query q = session.createQuery("select * from Dept d");查詢(xún)指定的列
值得注意的是:使用HQL查詢(xún)指定的列,返回的是對(duì)象數(shù)組Object[]
//只查詢(xún)name和eatBanana列Query query = session.createQuery("select m.name,m.eatBanana from Monkey m");System.out.println(query.list());?
?
封裝對(duì)象
前面測(cè)試了查詢(xún)指定的列的時(shí)候,返回的是對(duì)象數(shù)組...可是對(duì)象數(shù)組我們不好操作啊...Hibernate還提供了將對(duì)象數(shù)組封裝成對(duì)象的功能
- JavaBean要有對(duì)應(yīng)的構(gòu)造函數(shù)
條件查詢(xún)
在SQL中條件查詢(xún)我們也用得比較多,我們來(lái)看看HQL中的條件查詢(xún)有什么新特性。
占位符
占位符就是指?號(hào),我們?cè)赟QL中也常常用...
Query query = session.createQuery("from Monkey m where m.name=?");//HQL是從0開(kāi)始的query.setParameter(0, "大猴子");System.out.println(query.list());?
?
命名參數(shù)
HQL還支持命名參數(shù)查詢(xún)!下面我們來(lái)看一下怎么用:
語(yǔ)法::命名
Query query = session.createQuery("from Monkey m where m.name=:monkeyName");//HQL是從0開(kāi)始的query.setParameter("monkeyName", "大猴子");System.out.println(query.list());?
?
范圍查詢(xún)
范圍查詢(xún)就是使用between and關(guān)鍵字來(lái)查詢(xún)特定范圍的數(shù)據(jù)。。和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());模糊查詢(xún)
模糊查詢(xún)就是使用Like關(guān)鍵字進(jìn)行查詢(xún),和SQL也是一樣的。
- %號(hào)要寫(xiě)在參數(shù)上,不能寫(xiě)帶SQL上!
聚合函數(shù)統(tǒng)計(jì)
我們也經(jīng)常會(huì)查詢(xún)數(shù)據(jù)庫(kù)中一共有多少條記錄這樣的需求。那么在HQL中怎么用呢?
- HQL提供了uniqueResult()這么一個(gè)方法,返回只有一條記錄的數(shù)據(jù)
?
?
分組查詢(xún)
分組查詢(xún)和SQL是一樣的...
//-- 統(tǒng)計(jì)t_employee表中,每個(gè)部門(mén)的人數(shù)//數(shù)據(jù)庫(kù)寫(xiě)法:SELECT dept_id,COUNT(*) FROM t_employee GROUP BY dept_id;// HQL寫(xiě)法Query q = session.createQuery("select e.dept, count(*) from Employee e group by e.dept");System.out.println(q.list());連接查詢(xún)
連接查詢(xún)也就是多表查詢(xún)...多表查詢(xún)有三種
- 內(nèi)連接【等值連接】
- 左外連接
- 有外鏈接
值得注意的是:連接查詢(xún)返回的也是對(duì)象數(shù)組!
//1) 內(nèi)連接 【映射已經(jīng)配置好了關(guān)系,關(guān)聯(lián)的時(shí)候,直接寫(xiě)對(duì)象的屬性即可】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();迫切連接
由于連接查詢(xún)返回的是對(duì)象數(shù)組,我們使用對(duì)象數(shù)組來(lái)操作的話(huà)會(huì)很不方便...既然是連接查詢(xún),那么對(duì)象與對(duì)象是肯定有關(guān)聯(lián)關(guān)系的...于是乎,我們想把左表的數(shù)據(jù)填充到右表中,或者將右表的數(shù)據(jù)填充到左表中...使在返回的時(shí)候是一個(gè)對(duì)象、而不是對(duì)象數(shù)組!HQL提供了fetch關(guān)鍵字供我們做迫切連接~
//1) 迫切內(nèi)連接 【使用fetch, 會(huì)把右表的數(shù)據(jù),填充到左表對(duì)象中!】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();查詢(xún)語(yǔ)句放在配置文件中【命名查詢(xún)】
我們可以在具體的映射配置文件中存放一些常用的語(yǔ)句。以Dept為例
<!-- 存放sql語(yǔ)句,如果有<>這樣的字符數(shù)據(jù),需要使用CDATA轉(zhuǎn)義! --><query name="getAllDept"><![CDATA[from Dept d where deptId < ?]]></query>在程序中,我們可以獲取配置文件配置的語(yǔ)句
Query q = session.getNamedQuery("getAllDept");q.setParameter(0, 10);System.out.println(q.list());Criteria 查詢(xún)
Criteria是一種完全面向?qū)ο蟮牟樵?xún)...
Criteria使用的是add()來(lái)添加條件。條件又使用一個(gè)Restrictions類(lèi)來(lái)封裝
Criteria criteria = session.createCriteria(Monkey.class);criteria.add(Restrictions.eq())我們來(lái)簡(jiǎn)單看一下Restrictions的方法:
?
?
都是一些大于、小于、等于之類(lèi)的....Criteria查詢(xún)就使用不了分組、連接查詢(xún)了。
SQLQuery本地SQL查詢(xún)
有的時(shí)候,我們可能表的結(jié)構(gòu)十分復(fù)雜,如果使用關(guān)聯(lián)映射的話(huà),配置文件是十分臃腫的...因此,我們并不是把全部的數(shù)據(jù)表都使用映射的方式來(lái)創(chuàng)建數(shù)據(jù)表...
這時(shí),我們就需要用到SQLQuery來(lái)維護(hù)我們的數(shù)據(jù)了..
SQLQuery是不能跨數(shù)據(jù)庫(kù)的,因?yàn)镠ibernate在配置的時(shí)候就指定了數(shù)據(jù)庫(kù)的“方言”...
?
SQLQuery sqlQuery = session.createSQLQuery("SELECT * FROM monkey_ limit 0,3");System.out.println(sqlQuery.list());返回的也是對(duì)象數(shù)組:
?
?
Hibernate也支持在SQLQuery中對(duì)數(shù)據(jù)進(jìn)行對(duì)象封裝..只要添加類(lèi)型就行了
SQLQuery sqlQuery = session.createSQLQuery("SELECT * FROM monkey_ limit 0,3").addEntity(Monkey.class);System.out.println(sqlQuery.list());?
?
分頁(yè)查詢(xún)
傳統(tǒng)的SQL我們?cè)贒AO層中往往都是使用兩個(gè)步驟來(lái)實(shí)現(xiàn)分頁(yè)查詢(xún)
- 得到數(shù)據(jù)庫(kù)表中的總記錄數(shù)
- 查詢(xún)起始位置到末尾位數(shù)的數(shù)據(jù)
Hibernate對(duì)分頁(yè)查詢(xún)也有很好地支持,我們來(lái)一下:
Query query = session.createQuery("from Monkey");//得到滾動(dòng)結(jié)果集ScrollableResults scroll = query.scroll();//滾動(dòng)到最后一行scroll.last();int i = scroll.getRowNumber() + 1;System.out.println("總計(jì)路數(shù):" + i);//設(shè)置分頁(yè)位置query.setFirstResult(0);query.setMaxResults(3);System.out.println(query.list());- 提供了方法讓我們?cè)O(shè)置起始位置和結(jié)束位置
- 提供了ScrollableResults來(lái)得到滾動(dòng)結(jié)果集,最終得到總記錄數(shù)
值得注意的是,滾動(dòng)結(jié)果集是從0開(kāi)始的,因此需要+1才可得到總記錄數(shù)!
?
?
如果我們們使用的是SELECT COUNT(*) FROM 實(shí)體,我們可以通過(guò)uniqueResult()方法獲取數(shù)據(jù)的唯一記錄,得到的數(shù)據(jù)轉(zhuǎn)換成Long類(lèi)型即可。
Long totalRecord = (Long) queryCount.uniqueResult();Hibernate連接池
Hibernate自帶了連接池,但是呢,該連接池比較簡(jiǎn)單..而Hibernate又對(duì)C3P0這個(gè)連接池支持...因此我們來(lái)更換Hibernate連接池為C3P0
查看Hibernate自帶的連接池
我們可以通過(guò)Hibernate.properties文件中查看Hibernate默認(rèn)配置的連接池
hibernate.properties的配置文件可以在\project\etc找到
Hibernate的自帶連接池啥都沒(méi)有,就一個(gè)連接數(shù)量為1...
?
?
查看Hibernate對(duì)C3P0的支持
- #hibernate.c3p0.max_size 2 最大連接數(shù)
- #hibernate.c3p0.min_size 2 最小連接數(shù)
- #hibernate.c3p0.timeout 5000 超時(shí)時(shí)間
- #hibernate.c3p0.max_statements 100 最大執(zhí)行的命令的個(gè)數(shù)
- #hibernate.c3p0.idle_test_period 3000 空閑測(cè)試時(shí)間
- #hibernate.c3p0.acquire_increment 2 連接不夠用的時(shí)候, 每次增加的連接數(shù)
- #hibernate.c3p0.validate false
?
?
修改Hibernate連接池
我們?cè)趆ibernate.cfg.xml中配置C3p0,讓C30P0作為Hibernate的數(shù)據(jù)庫(kù)連接池
查找Hibernate支持的連接池組件有什么:
?
?
既然找到了,那么我們?cè)趆ibernate.cfg.xml中配置對(duì)應(yīng)的類(lèi)就和相關(guān)配置就行了
<!-- 【連接池配置】 --><!-- 配置連接驅(qū)動(dòng)管理類(lèi) --><property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property><!-- 配置連接池參數(shù)信息 --><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>線(xiàn)程Session使用
我們創(chuàng)建Session的時(shí)候,有兩個(gè)方法
- openSession()【每次都會(huì)創(chuàng)建新的Session】
- getCurrentSession()【獲取當(dāng)前線(xiàn)程的Session,如果沒(méi)有則創(chuàng)建】
一般地,我們使用線(xiàn)程Session比較多
如果要使用getCurrentSession(),需要在配置文件中配置:
<!--配置線(xiàn)程Session--><property name="hibernate.current_session_context_class">thread</property>測(cè)試數(shù)據(jù)
@Testpublic void testSession() throws Exception {//openSession: 創(chuàng)建Session, 每次都會(huì)創(chuàng)建一個(gè)新的sessionSession session1 = sf.openSession();Session session2 = sf.openSession();System.out.println(session1 == session2);session1.close();session2.close();//getCurrentSession 創(chuàng)建或者獲取session// 線(xiàn)程的方式創(chuàng)建session // 一定要配置:<property name="hibernate.current_session_context_class">thread</property>Session session3 = sf.getCurrentSession();// 創(chuàng)建session,綁定到線(xiàn)程Session session4 = sf.getCurrentSession();// 從當(dāng)前訪(fǎng)問(wèn)線(xiàn)程獲取sessionSystem.out.println(session3 == session4);// 關(guān)閉 【以線(xiàn)程方式創(chuàng)建的session,可以不用關(guān)閉; 線(xiàn)程結(jié)束session自動(dòng)關(guān)閉】//session3.close();//session4.close(); 報(bào)錯(cuò),因?yàn)橥粋€(gè)session已經(jīng)關(guān)閉了!}為什么要使用逆向工程
由于我們每次編寫(xiě)Hibernate的時(shí)候都需要寫(xiě)實(shí)體,寫(xiě)映射文件。而且Hibernate的映射文件也容易出錯(cuò)。而逆向工程可以幫我們自動(dòng)生成實(shí)體和映射文件,這樣就非常方便了。
使用PowerDesigner
在設(shè)計(jì)數(shù)據(jù)庫(kù)表時(shí),我們使用PowerDesigner來(lái)生成概念模型\物理模型...
設(shè)計(jì)一個(gè)人員組織架構(gòu):有機(jī)構(gòu)、部門(mén)、員工、領(lǐng)導(dǎo)、角色、權(quán)限。
- 一個(gè)機(jī)構(gòu)有多個(gè)部門(mén)
- 一個(gè)部門(mén)有多個(gè)員工
- 領(lǐng)導(dǎo)可以管理多個(gè)部門(mén),同時(shí)領(lǐng)導(dǎo)他自己也是員工
- 一個(gè)員工可以有多個(gè)角色
- 一個(gè)角色可以分配給多個(gè)人
- 人員角色分配后可以設(shè)置是否有效,分配時(shí)間等
- 一個(gè)角色有多個(gè)權(quán)限
概念模型:
?
?
在PowerDesigner中,箭頭指向的方向永遠(yuǎn)是“一”的一方
生成物理模型:
?
?
?
?
最后生成物理模型是這樣子的:
?
?
生成sql語(yǔ)句
我們可以單個(gè)生成,一個(gè)一個(gè)復(fù)制
?
?
也可以把整個(gè)物理模型的sql語(yǔ)句一起生成:
?
?
/*==============================================================*//* 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;在數(shù)據(jù)庫(kù)生成八張表:
?
?
在Idea下使用Hibernate逆向工程
?
?
值得注意的是:Intellij idea下生成出來(lái)的映射文件是沒(méi)有對(duì)應(yīng)的關(guān)聯(lián)關(guān)系的。也就是說(shuō):一對(duì)多或多對(duì)多的關(guān)系,它是不會(huì)幫你自動(dòng)生成的【好像是這樣子的】。。。因此,需要我們自己添加Set【如果需要】
更新,如果想要體現(xiàn)對(duì)應(yīng)的關(guān)聯(lián)關(guān)系的話(huà),請(qǐng)參考該博文!
- https://my.oschina.net/wangyuefive/blog/683771
如果文章有錯(cuò)的地方歡迎指正,大家互相交流。習(xí)慣在微信看技術(shù)文章,想要獲取更多的Java資源的同學(xué),可以關(guān)注微信公眾號(hào):Java3y
?
?
轉(zhuǎn)載于:https://my.oschina.net/u/3777556/blog/1631982
總結(jié)
以上是生活随笔為你收集整理的Hibernate【查询、连接池、逆向工程】的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【Java并发编程】20、DelayQu
- 下一篇: Linux下命令行的彩色终端