Hibernate-ORM:13.Hibernate中的連線查詢
------------吾亦無他,唯手熟爾,謙卑若愚,好學若飢-------------
本篇部落格將會解釋Hibernate中的連線查詢(各種join)
一,目錄
1.內連結
1.1顯式內連線(inner join)
1.1迫切顯式內連線(inner join fetch)
2.外連線
2.1左外連線(left join)
2.2迫切左外連線(left join fetch)
2.3以及為什麼我們在hibernate中儘量避免使用右外連線,具體的解釋
二,準備工作
1.資料庫指令碼的引用,我把測試需要的資料庫的指令碼給兄弟們傳一下
DROP TABLE IF EXISTS `dept`; CREATE TABLE `dept` ( `deptId` int(11) NOT NULL, `name` varchar(255) DEFAULT NULL, `location` varchar(255) DEFAULT NULL, PRIMARY KEY (`deptId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*Data for the table `dept` */ insert into `dept`(`deptId`,`name`,`location`) values (1,'xx部','1樓'),(2,'研發部','2樓'),(3,'銷售部','3樓'); /*Table structure for table `emp` */ DROP TABLE IF EXISTS `emp`; CREATE TABLE `emp` ( `empId` int(11) NOT NULL, `name` varchar(255) DEFAULT NULL, `sal` double DEFAULT NULL, `job` varchar(255) DEFAULT NULL, `deptNo` int(11) DEFAULT NULL, PRIMARY KEY (`empId`), KEY `FK110A81763AD08` (`deptNo`), CONSTRAINT `FK110A81763AD08` FOREIGN KEY (`deptNo`) REFERENCES `dept` (`deptId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*Data for the table `emp` */ insert into `emp`(`empId`,`name`,`sal`,`job`,`deptNo`) values (1,'a',10000,'財務猿1',1),(2,'Ab',5000,'財務猿2',1),(3,'bAa',6000,'財務猿3',1),(4,'aaA',100000,'程式猿1',2),(5,'aB',50000,'程式猿2',2),(6,'AC',60000,'程式猿3',2),(7,'AD',5000000,'Boss',NULL);
2.實體類的建立:值得注意的是toString()需要做手腳,否者就無限遞迴了
2.1Dept(部門的實體類)
package cn.dawn.day05.entity; import java.util.HashSet; import java.util.Set; /** * Created by Dawn on 2018/6/4. */ public class Dept { private Integer deptId; private String name; private String location; /*一個部門對應多個員工*/ private Set<Emp> emps=new HashSet<Emp>(); public Integer getDeptId() { return deptId; } public void setDeptId(Integer deptId) { this.deptId = deptId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getLocation() { return location; } public void setLocation(String location) { this.location = location; } public Set<Emp> getEmps() { return emps; } public void setEmps(Set<Emp> emps) { this.emps = emps; } @Override public String toString() { return "Dept{" + "deptId=" + deptId + ", name='" + name + '\'' + ", location='" + location + '\'' + '}'; } }
2.2Emp(員工實體類)
package cn.dawn.day05.entity; /** * Created by Dawn on 2018/6/4. */ public class Emp { private Integer empId; private String name; private String job; private Double sal; //多個員工屬於一個部門 private Dept dept; public Integer getEmpId() { return empId; } public void setEmpId(Integer empId) { this.empId = empId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getJob() { return job; } public void setJob(String job) { this.job = job; } public Double getSal() { return sal; } public void setSal(Double sal) { this.sal = sal; } public Dept getDept() { return dept; } public void setDept(Dept dept) { this.dept = dept; } @Override public String toString() { return "Emp{" + "empId=" + empId + ", name='" + name + '\'' + ", job='" + job + '\'' + ", sal=" + sal + ", dept=" + dept + '}'; } }
3.hbm.xml小配置的配置
3.1Dept.hbm.xml的配置
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="cn.dawn.day05.entity"> <!--如果上面指定package的話,class的name就不必寫全類名--> <!--lazy:是否懶載入(延遲載入) 預設值是true,延遲載入--> <!--<class name="Teacher">--> <!--直接載入--> <class name="Dept" lazy="false"> <!--主鍵--> <id name="deptId" column="deptId"> <!--主鍵生成策咯 assigned程式設計師自己建立--> <!--identity是mysql裡的自增,一會做增加操作不必再給主鍵賦值--> <!--increment是先查最大的主鍵列,在下一條給主鍵加一--> <!--sequence是oracle的主鍵生成策咯,他一會需要指定序列名字<param name="sequence">序列名</param>--> <generator class="assigned"></generator> </id> <property name="name"/> <property name="location"/> <!--table指的是中間表,承載關聯關係的表--> <set name="emps" cascade="all" inverse="true"> <key> <!--本類表的id--> <column name="deptNo"/> </key> <!--另外與他有多對多關聯的實體類--> <one-to-many class="Emp"/> </set> </class> </hibernate-mapping>
3.2Emp.hbm.xml小配置的配置
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="cn.dawn.day05.entity"> <!--如果上面指定package的話,class的name就不必寫全類名--> <!--lazy:是否懶載入(延遲載入) 預設值是true,延遲載入--> <!--<class name="Teacher">--> <!--直接載入--> <class name="Emp" lazy="false"> <!--主鍵--> <id name="empId" column="empId"> <!--主鍵生成策咯 assigned程式設計師自己建立--> <!--identity是mysql裡的自增,一會做增加操作不必再給主鍵賦值--> <!--increment是先查最大的主鍵列,在下一條給主鍵加一--> <!--sequence是oracle的主鍵生成策咯,他一會需要指定序列名字<param name="sequence">序列名</param>--> <generator class="assigned"></generator> </id> <property name="name"/> <property name="sal"/> <property name="job"/> <!--table指的是中間表,承載關聯關係的表--> <!--另外與他有多對多關聯的實體類--> <many-to-one name="dept" column="deptNo" class="Dept"/> </class> </hibernate-mapping>
4.hibernate.cfg.xml這個Hibernate核心配置的配置
<?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> <!--jdbc連線四要素--> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql:///y2167</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password"></property> <!--在控制檯上展示sql--> <property name="show_sql">true</property> <!--格式化sql--> <!--<property name="format_sql">true</property>--> <!--====================================================================--> <!--ddl操作生成策咯,每次執行都在原有表上修改,沒有的話就建立表--> <!-- <property name="hbm2ddl.auto"></property> key - hbm2ddl.auto:自動生成表結構策略 value - update(使用最多):當資料庫不存在表時,hibernate啟動後會自動生成表結構。 當資料庫表存在時,如果一樣,則只會寫入資料,不會改變表結構。 當資料庫表存在時,如果不一樣,則會修改表結構,原有的表結構不會改變。 create(很少):無論表結構是否存在,hibernate啟動後都會重新生成表結構。(造成之前的資料丟失) create-drop(極少):無論表結構是否存在,hibernate啟動都會重新生成表結構。並且hibernate關閉後,表結構會被刪除。來無影去無蹤。 validate(很少):不會建立表結構,不會修改表結構。校驗與資料庫中的表結構是否一樣,如果不一樣則報異常。 --> <property name="hbm2ddl.auto">update</property> <!--使用getCurrentSession()需要配置此標籤--> <property name="current_session_context_class">thread</property> <!--與小配置檔案對映--> <mapping resource="cn/dawn/day05/dao/Dept.hbm.xml"></mapping> <mapping resource="cn/dawn/day05/dao/Emp.hbm.xml"></mapping> </session-factory> </hibernate-configuration>
三,顯式內連線(inner join)
@Test /*內連線*/ /*返回的是Object[]陣列,只有6條資料*/ public void t1innerjoin(){ String hql="from Emp e inner join e.dept"; List<Object[]> list = session.createQuery(hql).list(); for(Object[] o:list){ System.out.println(o[0]);//Emp物件 System.out.println(o[1]);//Dept物件 } /* Hibernate: alter table Emp add constraint FK42q0wt6tw3e1tcygsbj6pexh foreign key (deptNo) references Dept (deptId) Hibernate: select emp0_.empId as empId1_1_0_, dept1_.deptId as deptId1_0_1_, emp0_.name as name2_1_0_, emp0_.sal as sal3_1_0_, emp0_.job as job4_1_0_, emp0_.deptNo as deptNo5_1_0_, dept1_.name as name2_0_1_, dept1_.location as location3_0_1_ from Emp emp0_ inner join Dept dept1_ on emp0_.deptNo=dept1_.deptId Emp{empId=1, name='a', job='財務猿1', sal=10000.0, dept=Dept{deptId=1, name='xx部', location='1樓'}} Dept{deptId=1, name='xx部', location='1樓'} Emp{empId=2, name='Ab', job='財務猿2', sal=5000.0, dept=Dept{deptId=1, name='xx部', location='1樓'}} Dept{deptId=1, name='xx部', location='1樓'} Emp{empId=3, name='bAa', job='財務猿3', sal=6000.0, dept=Dept{deptId=1, name='xx部', location='1樓'}} Dept{deptId=1, name='xx部', location='1樓'} Emp{empId=4, name='aaA', job='程式猿1', sal=100000.0, dept=Dept{deptId=2, name='研發部', location='2樓'}} Dept{deptId=2, name='研發部', location='2樓'} Emp{empId=5, name='aB', job='程式猿2', sal=50000.0, dept=Dept{deptId=2, name='研發部', location='2樓'}} Dept{deptId=2, name='研發部', location='2樓'} Emp{empId=6, name='AC', job='程式猿3', sal=60000.0, dept=Dept{deptId=2, name='研發部', location='2樓'}} Dept{deptId=2, name='研發部', location='2樓'} * */ }
四,迫切顯式內連線(inner join fetch)
@Test /*迫切內連線*/ /*返回的是Object,只有6條資料*/ public void t2innerjoinFetch(){ String hql="from Emp e inner join fetch e.dept"; List<Emp> list = session.createQuery(hql).list(); for(Emp e:list){ System.out.println(e);//Emp物件 } /* Hibernate: select emp0_.empId as empId1_1_0_, dept1_.deptId as deptId1_0_1_, emp0_.name as name2_1_0_, emp0_.sal as sal3_1_0_, emp0_.job as job4_1_0_, emp0_.deptNo as deptNo5_1_0_, dept1_.name as name2_0_1_, dept1_.location as location3_0_1_ from Emp emp0_ inner join Dept dept1_ on emp0_.deptNo=dept1_.deptId Emp{empId=1, name='a', job='財務猿1', sal=10000.0, dept=Dept{deptId=1, name='xx部', location='1樓'}} Emp{empId=2, name='Ab', job='財務猿2', sal=5000.0, dept=Dept{deptId=1, name='xx部', location='1樓'}} Emp{empId=3, name='bAa', job='財務猿3', sal=6000.0, dept=Dept{deptId=1, name='xx部', location='1樓'}} Emp{empId=4, name='aaA', job='程式猿1', sal=100000.0, dept=Dept{deptId=2, name='研發部', location='2樓'}} Emp{empId=5, name='aB', job='程式猿2', sal=50000.0, dept=Dept{deptId=2, name='研發部', location='2樓'}} Emp{empId=6, name='AC', job='程式猿3', sal=60000.0, dept=Dept{deptId=2, name='研發部', location='2樓'}} * */ }
五,左外連線(left join)
@Test /*左外連線*/ /*返回的是Object[]陣列,有7條資料,多出來一條,以Emp表為準*/ public void t3leftjoin(){ String hql="from Emp e left join e.dept"; List<Object[]> list = session.createQuery(hql).list(); for(Object[] o:list){ System.out.println(o[0]);//Emp物件 System.out.println(o[1]);//Dept物件 } /* Hibernate: select emp0_.empId as empId1_1_0_, dept1_.deptId as deptId1_0_1_, emp0_.name as name2_1_0_, emp0_.sal as sal3_1_0_, emp0_.job as job4_1_0_, emp0_.deptNo as deptNo5_1_0_, dept1_.name as name2_0_1_, dept1_.location as location3_0_1_ from Emp emp0_ left outer join Dept dept1_ on emp0_.deptNo=dept1_.deptId Emp{empId=1, name='a', job='財務猿1', sal=10000.0, dept=Dept{deptId=1, name='xx部', location='1樓'}} Dept{deptId=1, name='xx部', location='1樓'} Emp{empId=2, name='Ab', job='財務猿2', sal=5000.0, dept=Dept{deptId=1, name='xx部', location='1樓'}} Dept{deptId=1, name='xx部', location='1樓'} Emp{empId=3, name='bAa', job='財務猿3', sal=6000.0, dept=Dept{deptId=1, name='xx部', location='1樓'}} Dept{deptId=1, name='xx部', location='1樓'} Emp{empId=4, name='aaA', job='程式猿1', sal=100000.0, dept=Dept{deptId=2, name='研發部', location='2樓'}} Dept{deptId=2, name='研發部', location='2樓'} Emp{empId=5, name='aB', job='程式猿2', sal=50000.0, dept=Dept{deptId=2, name='研發部', location='2樓'}} Dept{deptId=2, name='研發部', location='2樓'} Emp{empId=6, name='AC', job='程式猿3', sal=60000.0, dept=Dept{deptId=2, name='研發部', location='2樓'}} Dept{deptId=2, name='研發部', location='2樓'} Emp{empId=7, name='AD', job='Boss', sal=5000000.0, dept=null} null * */ }
六,迫切左外連線(left join fetch)
@Test /*迫切左外連線*/ /*返回的是Object,有7條資料*/ public void t4leftjoinFetch(){ String hql="from Emp e left join fetch e.dept"; List<Emp> list = session.createQuery(hql).list(); for(Emp e:list){ System.out.println(e);//Emp物件 } /* Hibernate: select emp0_.empId as empId1_1_0_, dept1_.deptId as deptId1_0_1_, emp0_.name as name2_1_0_, emp0_.sal as sal3_1_0_, emp0_.job as job4_1_0_, emp0_.deptNo as deptNo5_1_0_, dept1_.name as name2_0_1_, dept1_.location as location3_0_1_ from Emp emp0_ left outer join Dept dept1_ on emp0_.deptNo=dept1_.deptId Emp{empId=1, name='a', job='財務猿1', sal=10000.0, dept=Dept{deptId=1, name='xx部', location='1樓'}} Emp{empId=2, name='Ab', job='財務猿2', sal=5000.0, dept=Dept{deptId=1, name='xx部', location='1樓'}} Emp{empId=3, name='bAa', job='財務猿3', sal=6000.0, dept=Dept{deptId=1, name='xx部', location='1樓'}} Emp{empId=4, name='aaA', job='程式猿1', sal=100000.0, dept=Dept{deptId=2, name='研發部', location='2樓'}} Emp{empId=5, name='aB', job='程式猿2', sal=50000.0, dept=Dept{deptId=2, name='研發部', location='2樓'}} Emp{empId=6, name='AC', job='程式猿3', sal=60000.0, dept=Dept{deptId=2, name='研發部', location='2樓'}} Emp{empId=7, name='AD', job='Boss', sal=5000000.0, dept=null} * */ }
七,以及為什麼我們在hibernate中儘量避免使用右外連線,具體的解釋
以右表為準,返回的左表物件,如果右表有一個null值做關聯,那麼左表的物件就是null,如果把這個物件直接訪問其屬性,就會引發空指標異常
所以,我們一般不會使用右外連線
@Test /*迫切右外連線*/ /*返回的是Object,*/ /*hibernate中一般不使用他,不是不能用,而是特別容易出現空指標的異常*/ /*注意觀察最後一行查出來的資料,如果我用訪問他的屬性,這就很難受了*/ /*public void t5rightjoinFetch(){ String hql="from Emp e right join fetch e.dept"; List<Emp> list = session.createQuery(hql).list(); for(Emp e:list){ System.out.println(e);//Emp物件 } *//* Hibernate: select emp0_.empId as empId1_1_0_, dept1_.deptId as deptId1_0_1_, emp0_.name as name2_1_0_, emp0_.sal as sal3_1_0_, emp0_.job as job4_1_0_, emp0_.deptNo as deptNo5_1_0_, dept1_.name as name2_0_1_, dept1_.location as location3_0_1_ from Emp emp0_ right outer join Dept dept1_ on emp0_.deptNo=dept1_.deptId Emp{empId=1, name='a', job='財務猿1', sal=10000.0, dept=Dept{deptId=1, name='xx部', location='1樓'}} Emp{empId=2, name='Ab', job='財務猿2', sal=5000.0, dept=Dept{deptId=1, name='xx部', location='1樓'}} Emp{empId=3, name='bAa', job='財務猿3', sal=6000.0, dept=Dept{deptId=1, name='xx部', location='1樓'}} Emp{empId=4, name='aaA', job='程式猿1', sal=100000.0, dept=Dept{deptId=2, name='研發部', location='2樓'}} Emp{empId=5, name='aB', job='程式猿2', sal=50000.0, dept=Dept{deptId=2, name='研發部', location='2樓'}} Emp{empId=6, name='AC', job='程式猿3', sal=60000.0, dept=Dept{deptId=2, name='研發部', location='2樓'}} null * *//* }*/
相關文章
- 連線查詢
- MySql中的資料查詢語言(DQL)三:連線查詢MySql
- select查詢中union連線符
- SQL連線查詢SQL
- oracle 連線查詢Oracle
- 【Oracle】--連線查詢Oracle
- 連線查詢中不等式的運用
- sql 連線查詢例項(left join)三表連線查詢SQL
- 資料庫資料的查詢----連線查詢資料庫
- MySQL之連線查詢和子查詢MySql
- mysql查詢語句5:連線查詢MySql
- select查詢之四:連線查詢
- MySQL之連線查詢MySql
- 資料庫 - 連線查詢、巢狀查詢、集合查詢資料庫巢狀
- mysql-分組查詢-子查詢-連線查詢-組合查詢MySql
- myeclipse 中java連線mysql、查詢測試EclipseJavaMySql
- oracle連線查詢詳解Oracle
- MySQL學習-連線查詢MySql
- Hibernate連線查詢join
- 【janes】多表查詢 外連線
- MySQL8:連線查詢MySql
- 水煮oracle31----連線查詢&合併查詢Oracle
- 在 SQL Server 中查詢活動連線和死鎖SQLServer
- /*+ MERGE_AJ */ 放到NOT IN 子查詢中反向連線
- 查詢表中的連結行
- MySQL內連線查詢語句MySql
- 分組查詢連線號段
- Sql Server系列:多表連線查詢SQLServer
- SQL複雜查詢多表連線SQL
- SQL裡3個表的連線查詢SQL
- oracle心得4--集合查詢@oracle中的多表連線@案例分析Oracle
- 3.DQL資料查詢語言(內連線,外連線,自連線)
- MySQL 連線查詢超全詳解MySql
- Hibernate【查詢、連線池、逆向工程】
- PHP連線、查詢MySQL資料庫PHPMySql資料庫
- HTTP協議中的短輪詢、長輪詢、長連線和短連線HTTP協議
- 【大資料】SparkSql連線查詢中的謂詞下推處理(一)大資料SparkSQL
- 【大資料】SparkSql 連線查詢中的謂詞下推處理 (二)大資料SparkSQL