Hibernate 查詢與多表操作

Hibernate主鍵ID生成方式

數據庫中表有主鍵、主鍵的唯一性決定了數據庫表中記錄唯一。緩存在Session中的數據即實例都有一個唯一的ID,ID映射了數據庫中主鍵。那麼ID如何產生呢?

1、assigned:主鍵由外部程序負責生成,無需Hibernate參與。即當增加一個實體時,由程序設定它的ID值(手工分配值)

<class name="bean.Customer" table="customers" catalog="support">
        <id name="customerId" type="java.lang.String">
            <column name="customerID" length="8" />
            <generator class="assigned"></generator>
        </id>
        .......
</class>


 

2、identity:在DB2、SQL Server、MySQL等數據庫產品中表中主鍵列可以設定是自動增長列,則增加一條記錄時主鍵的值可以不賦值。用數據庫提供的主鍵生成機制。

(1) 表結構:
 create table test1 (   tid int not null  primary key auto_increment,
name char(40));
  (2) 映射文件
    <class name="bean.Test1" table="test1" catalog="support">
        <id name="tid" type="java.lang.Integer">
            <column name="tid" />
            <generator class="identity"></generator>
        </id>
        <property name="name" type="java.lang.String">
            <column name="name" length="40" />
        </property>
    </class>


 

3、increment:主鍵按數值順序遞增。此方式的實現機制爲在當前應用實例中維持一個變量,以保存着當前的最大值,之後每次需要生成主鍵的時候將此值加1作爲主鍵。這種方式可能產生的問題是:如果當前有多個實例訪問同一個數據庫,那麼由於各個實例各自維護主鍵狀態,不同實例可能生成同樣的主鍵,從而造成主鍵重複異常。因此,如果同一數據庫有多個實例訪問,此方式必須避免使用。


 

4、sequence: 採用數據庫提供的sequence 機制生成主鍵。 

     如Oralce中的Sequence,在Oracle中創建序列:

           create sequence hibernate_sequence;

     當需要保存實例時,Hibernate自動查詢Oracle中序列"hibernate_sequence"的下一個值;該值作爲主鍵值。可以改變默認的序列名稱。

5、native:由Hibernate根據底層數據庫自行判斷採用identity、hilo、sequence其中一種作爲主鍵生成方式。

6、uuid.hex:由Hibernate爲ID列賦值,依據當前客戶端機器的IP、JVM啓動時間、當前時間、一個計數器生成串,以該串爲ID值。

Hibernate 查詢方式

1、Hibernate查詢HQL語句

限制查詢結果記錄數與起始記錄
Session session=HibernateSessionFactory.getSession();
Query query=session.createQuery("from Customer");
query.setFirstResult(10); //設置查詢記錄開始位置,索引從0開始。
query.setMaxResults(10);//設置查詢返回的最大記錄個數。
List list=query.list();
注意:條件查詢
Session session=HibernateSessionFactory.getSession();
Query query=session.createQuery("from Customer cus where cus.name='zhou'");


 

 2、取表中部分列時

(1) 單一屬性查詢。還是返回一個集合,只不過集合中存儲的不是表的實例而是對象。
Session session = null;
session = HibernateSessionFactory.getSession();
List cnames = session.createQuery("select cname from Customer").list();
for (int i=0;i< cnames.size();i++) {
		String name = (String)cnames.get(i);
		System.out.println(name);
}


 

(2) 多個屬性的查詢,使用對象數組。
Session session = null;
session = HibernateSessionFactory.getSession();
//查詢多個屬性,其集合元素是對象數組
//數組元素的類型,跟實體類的屬性的類型相關
List students = session.createQuery("select sno, sname from Students").list();
for (int i=0;i< students.size();i++) {
		Object[] obj = (Object[])students.get(i);
		System.out.println(obj[0] + ", " + obj[1]);
}


 

 (3) 多個屬性的查詢,使用List集合裝部分列

Session session = HibernateSessionFactory.getSession();
Query query = session.createQuery("select new list(cus.name,cus.phone) from Customer cus");
List list = query.list();
for (int i = 0; i < list.size(); i++) {
	List temp=(List)list.get(i);
	System.out.println(temp.get(0));  //0是索引
}


 

 (4) 使用Map集合裝部分列

Session session = HibernateSessionFactory.getSession();
Query query = session.createQuery("select new map(cus.name,cus.phone) from Customer cus");
List list = query.list();
for (int i = 0; i < list.size(); i++) {
	Map temp=(Map)list.get(i);
	System.out.println(temp.get("1"));  //"1"是key
}


 3、內連接 

Query query=session.createQuery("select c.name, s.name from Student s join s.classes c ").list();
for (Iterator iter = students.iterator();iter.hasNext();) {
	Object[] obj = (Object[])iter.next();
	System.out.println(obj[0] + ", " + obj[1]);
}


 

4、外連接

select c.name, s.name from Classes c left join c.students s 
select c.name, s.name from Classes c right join c.students s 


 

5、帶參數的查詢

(1)  ?作爲參數 如" from Customer cus where cus.name=?";
     Session session = HibernateSessionFactory.getSession();
    Query query = session.createQuery("from Customer cus where cus.name=?");
     query.setParameter(0, "zhou");
     List list = query.list();
(2)  參數名稱  :name   如" from Customer cus where cus.name=:name";
Session session = HibernateSessionFactory.getSession();
	   Query query = session.createQuery("from Customer cus where cus.name=:name ");
	   query.setParameter("name", "zhou");
	   List list = query.list();
(3)  條件查詢,使用 ?的方式傳遞參數
	 Query query = session.createQuery("SELECT s.id, s.name FROM Student s WHERE s.name LIKE ?");
	 query.setParameter(0, “%周%”); //傳遞參數參數的索引是從0開始的。   如條件查詢,使用":參數"名稱的方式傳遞參數
	Query query = session.createQuery("SELECT s.id, s.name FROM Student s WHERE s.name LIKE :myname");
	query.setParameter("myname", "張三");//傳遞參數
因爲setParameter方法返回Query接口,所以可用省略方式來查詢
List students = session.createQuery("SELECT s.id, s.name FROM Student s WHERE s.name LIKE :myname and s.id = :myid")
setParameter("myname", "%周%").setParameter("myid", 15).list();


 

6、嵌入原生sql測試

SQLQuery sqlQuery = session.createSQLQuery("select * from t_student");
	List students = sqlQuery.list();
	for (Iterator iter = students.iterator();iter.hasNext();) {
		Object[] obj = (Object[])iter.next();
		System.out.println(obj[0] + ", " + obj[1]);
	}


Hibernate多表操作

       關係型數據庫具有三種常用關係:一對一關係、一對多關係和多對多關係。

       建立了一對多關係的表之間,一方中的表叫“主表”,多方中的表叫“子表”;兩表中相關聯的字段,在主表中叫“主鍵”,在子表中稱“外鍵”。

級聯操作與延遲加載

1、cascade級聯操作

    所謂cascade,如果有兩個表,在更新一方的時候,可以根據對象之間的關聯關係,對被關聯方進行相應的更新。

all :所有情況下均進行關聯操作。

none:所有情況下均不進行關聯操作。這是默認值。

save-update:執行save/update/saveOrUpdate時進行關聯操作

delete:在執行delete時進行關聯操作。

2、inverse屬性

3、延遲加載

(1) 屬性的延遲加載

Person表有一個人員圖片字段(對應java.sql.Clob類型)屬於大數據對象,當我們加載該對象時,我們不得不每一次都要加載這個字段,而不論我們是否真的需要它,而且這種大數據對象的讀取本身會帶來很大的性能開銷。我們可以如下配置我們的實體類的映射文件

<hibernate-mapping>
 <class name="bean.Person" table="person">
      ……
  <property name="pimage" type="java.sql.Clob" 
                         column="pimage" lazy="true"/>
 </class>
 </hibernate-mapping>


代碼:

當寫完上一個單表操作時,發現再進行多表操作時,student的外鍵dept不能再用string,而應該是建一個對象。在多表級聯操作時,都應建一個對象

爲了減少冗餘,這裏只貼出關鍵代碼。

HibDemoServlet.java

package cn.hncu.servlet;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.hncu.domain.Dept;
import cn.hncu.domain.Student;
import cn.hncu.service.HibDemoServiceImpl;
import cn.hncu.utils.BaseServlet;

public class HibDemoServlet extends BaseServlet {
	private HibDemoServiceImpl service=new HibDemoServiceImpl();
	@Override
	public void execute(HttpServletRequest req, HttpServletResponse resp)
			throws Exception {
		List<Dept> list=service.queryAllDepts();
		req.setAttribute("list",list);
		String resultPage=getInitParameter("show");
		req.getRequestDispatcher(resultPage).forward(req, resp);
	}
	public void queryDept(HttpServletRequest req, HttpServletResponse resp)
			throws Exception {
		String deptId=req.getParameter("deptId");
		String deptName=req.getParameter("deptName");
		Dept dept=new Dept();
		dept.setDeptId(deptId);
		dept.setDeptName(deptName);
		
		List<Dept> depts=service.queryDept(dept);
		req.getSession().setAttribute("depts", depts);
		resp.sendRedirect(req.getContextPath()+"/jsps/qresult.jsp");
	}
	public void addDept(HttpServletRequest req, HttpServletResponse resp)
			throws Exception {
		//按理添加數據的時候應該從前臺獲取數據然後進行封裝,這裏省略了
		Dept dept=new Dept();
		dept.setDeptId("D004");
		dept.setDeptName("外國語學院");
		
		Student stud1=new Student();
		stud1.setId("S008");
		stud1.setName("S1");
		stud1.setAge(18);
		stud1.setDept(dept);//注:多方要添加一方
		Student stud2=new Student();
		stud2.setId("S009");
		stud2.setName("S2");
		stud2.setAge(19);
		stud2.setDept(dept);
		
		dept.getStudents().add(stud1);//一方添加多方
		dept.getStudents().add(stud2);
		
		try {
			service.addDept(dept);
			System.out.println("添加成功!");
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("添加失敗!");
		}
	}
}


show.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
	  <style type="text/css">
	  		table{
	  			border: 1px solid blue;
	  			border-collapse: collapse;
	  			width:60%;
	  		}
	  		td,th{
	  			border: 1px solid blue;
	  			padding: 5px;
	  		}
	  		#t2 tr{
	  			text-align: center;
	  		}
	  		iframe{
	  			height: 50%;
	  			width: 60%;
	  		}
  	  </style>
  </head>
  <body>
    <h2>演示Hibernate進行表與表之間操作</h2>
    <table>
    	<tr align="center">
    		<th>學院編號</th>
    		<th>學院名稱</th>
    	</tr>
    	
    	<c:forEach items="${list}" var="dept">
    		<tr align="center">
    			<td>${dept.deptId }</td>
    			<td>${dept.deptName }</td>
    		</tr>
    	</c:forEach>
    </table>
    <br/><br/><br/>
    <h3>學生詳細信息查詢</h3>
    <form action="<c:url value='/HibDemoServlet?cmd=queryDept' />" method="post" target="f1">
    	<table id="t2">
    		<tr>
    			<td>學院編號</td><td><input type="text" name="deptId" /></td>
    		</tr>
    		<tr>
    			<td>學院名稱</td><td><input type="text" name="deptName" /></td>
    		</tr>
    		<tr>
    			<td colspan="2"><input type="submit" value="查詢"/></td>
    		</tr>
    	</table>
    </form>
    
    <iframe name="f1" ></iframe><br/><br/>
    
    <a href="<c:url value='/HibDemoServlet?cmd=addDept' />">Hibernate中表與表之間的級聯操作</a>
    <br/> <br/> <br/><br/><br/>
  </body>
</html>
   


Student.java

package cn.hncu.domain;
/*
 * 要在hibernate中實現表與表之間的關係(以一對多爲例)
 */
public class Student {
	private String id;
	private String name;
	private Integer age;
	
	//添加一個用於存儲一方的對象
	private Dept dept;
	public Dept getDept() {
		return dept;
	}
	public void setDept(Dept dept) {
		this.dept = dept;
	}
	
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	
	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + ", age=" + age
				+ ", dept=" + dept + "]";
	}
	
}


Dept.java

package cn.hncu.domain;

import java.util.HashSet;
import java.util.Set;
/*
 * 要在hibernate中實現表與表之間的關係(以一對多爲例)
 */
public class Dept {
	
	private String deptId;
	private String deptName;
	
	//添加一個用於存儲多方的集合
	private Set<Student> students=new HashSet<Student>();//一定要提前new 出來,不然會出現空指針異常
	
	public Set<Student> getStudents() {
		return students;
	}
	public void setStudents(Set<Student> students) {
		this.students = students;
	}
	
	public String getDeptId() {
		return deptId;
	}
	public void setDeptId(String deptId) {
		this.deptId = deptId;
	}
	public String getDeptName() {
		return deptName;
	}
	public void setDeptName(String deptName) {
		this.deptName = deptName;
	}
	@Override
	public String toString() {
		return "Dept [deptId=" + deptId + ", deptName=" + deptName + "]";
	}
	
}


Student.hib.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 package="cn.hncu.domain">
	<class name="Student" table="students" catalog="hib">
		<id name="id" column="id" type="java.lang.String"></id>
		<property name="name" >
			<column name="name"></column>
		</property>
		<property name="age">
			<column name="age"></column>
		</property>
	
		<!-- 在hibernate中實現表與表之間關係(以一對多爲例) -->
		<!-- 下面這一段是相比單表不同的地方,配置多對一的關係即值對象中的"dept"屬性 -->
		<many-to-one name="dept" class="Dept" fetch="select">
			<column name="deptId"></column>
		</many-to-one>
		
	</class>
	
	
	<class name="Dept" catalog="hib" table="depts">
		<id name="deptId" type="java.lang.String">
			<column name="id" length="8"></column>
			<generator class="assigned"></generator><!-- 主鍵由外部程序負責生成,無需Hibernate參與。即當增加一個實體時,由程序設定它的ID值(手工分配值) -->
		</id>
		<property name="deptName" column="name"></property>
	
		<!-- 在hibernate中實現表與表之間關係(以一對多爲例) -->
		<!-- 下面這一段是相比單表不同的地方,配置多對一的關係即值對象中的"students"集合屬性 -->
		<set name="students" table="students" inverse="true" cascade="all"> 
			<key>
				<column name="deptId"></column>
			</key>
			<one-to-many class="Student"/>
		</set>
	
	</class>
</hibernate-mapping>


HibDemoJdbc.java

package cn.hncu.dao;

import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;

import cn.hncu.domain.Dept;
import cn.hncu.domain.Student;
import cn.hncu.hib.HibernateSessionFactory;

public class HibDemoJdbcDao {
	public List<Dept> queryAllDepts(){
		Session session=HibernateSessionFactory.getSession();
		//SQL  ---Structured Query Language ---面向R(關係--表)
		//HQL  ---Hibernate Query Language ---面向O(值對象)
		Query query=session.createQuery("from Dept");//HQL
		List<Dept> depts=query.list();
		return depts;
	}
	
	//條件查詢
	public List<Dept> queryDept(Dept dept) {
		Session session=HibernateSessionFactory.getSession();
		//清緩存
		session.clear();
		
		String hql="from Dept d where 1=1";
		String deptId=dept.getDeptId();
		String deptName=dept.getDeptName();
		int flag=0;
		//HQL語句中的類字段,是java類中的字段,不是數據庫中的字段;
		if(deptId!=null&&deptId.trim().length()>0){
			hql+="and d.deptId=?";
			flag|=1;
		}
		if(deptName!=null&&deptName.trim().length()>0){
			hql+="and d.deptName like ?";
			flag|=2;
		}
		Query query=session.createQuery(hql);
		if(flag==1||flag==3){
			query.setParameter(0, deptId.trim());
		}
		if(flag==2){
			query.setParameter(0, "%"+deptName+"%");//模糊查詢
		}
		if(flag==3){
			query.setParameter(1, "%"+deptName.trim()+"%");
		}
		List<Dept> depts= query.list();
		return depts;
	}

	public void addDept(Dept dept) {
		Session session=HibernateSessionFactory.getSession();
		Transaction tr=session.beginTransaction();
		session.save(dept);//只能進行添加,若id存在則添加失敗
		tr.commit();//必須進行事務提交才能保存到數據庫
	}
}


qresult.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
	  <style type="text/css">
	  		table{
	  			border: 1px solid blue;
	  			border-collapse: collapse;
	  			width:60%;
	  		}
	  		td,th{
	  			border: 1px solid blue;
	  			padding: 5px;
	  		}
	  		#t2 tr{
	  			text-align: center;
	  		}
	  		
  	  </style>
  </head>
  <body>
  	<h2>學院基本信息</h2>
   	<c:forEach items="${depts}" var="dept">
	    編號:${dept.deptId} , 名稱:${dept.deptName}
	    <table>
	    	<tr align="center">
	    		<th>學號</th>
	    		<th>姓名</th>
	    		<th>年齡</th>
	    	</tr>
		    	<c:forEach items="${dept.students}" var="student">
		    		<tr align="center">
		    			<td>${student.id }</td>
		    			<td>${student.name }</td>
		    			<td>${student.age }</td>
		    		</tr>
		    	</c:forEach>
	    </table>
  	</c:forEach>
    <br/><br/><br/>
  </body>
</html>
   

 

//清hibernate緩存
  session.clear();


效果展示:

發佈了121 篇原創文章 · 獲贊 49 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章