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();


效果展示:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值