Hibernate授课提纲 (2)
Hibernate授课提纲
一、回顾JDBC数据库操作
二、了解反射基本原理和作用
三、了解ORM,明白ORM是什么?
四、Hibernate的相关配置
五、简单的Hibernate应用
重点内容:
Hibernate的相关配置与应用
1什么是反射
通俗的讲,反射机制就是在不知道一个类有多少属性和方法的情况下,循环遍历出所有的属性和方式等并能赋值和取值。
在Java类中本身就拥有大量的集合,这些集合就已经包括了属性集合,方法集合等,我们只要遍历出属性或方法就能得到这些具体的属性和方法来,并赋值和取值。
比如:
Class> demo=Class.forName("Reflect.Person");
Person per=(Person)demo.newInstance();//自动转换为具体的实例
per.setName("Rollen");
2什么是ORM
对象关系映射(Object Relational Mapping,简称ORM)是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技巧。
简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将java程序中的对象自动长久化到关系数据库中。本质上就是将数据从一种模式转换到另外一种模式。其中Hibernate 的轻量级ORM 模型在Java ORM 架构中处于领导地位。
简单的讲,ORM就是通过一种类型转换为另外一种类型,比如数据库中有一张表,User(uid,uname),建立一个类UserInfo(uid,uname)与表结构对应,采用UserInfo.uid=User.uid方式可以为类赋值,但是如果UserInfo为(id,name),那么就需要对应UserInfo.id=User.uid
思考:
1)能不能固定UserInfo的字段和表中名字相同,或采用什么方式来指定
2)UserInfo中的字段名可以通过反射来得到,而User中的字段名和数据都可以采用
SQL语句来得到。两者之间通过循环对比的方式就可以把数据库中User表中的数
据放入到UserInfo实例中,这样就完成了一种数据结构转换到另外一种数据结构
中
问题:什么叫持久化过程?
持久化是将程序中的数据在瞬间状态和持久状态间转换的机制。就是把数据保存到数据库或其它介质中。
3Hibernate配置
Hibernate也是一个框架,主要目的是代替简化JDBC对数据库的操作。它就是利用反射,ORM等技术来进行实现。由于Hibernate内部已经实现了很多功能,所以我们第一步就是掌握如何使用它,然后掌握它的原理,最后仿照它来实现一个新的框架。
首先在项目中添加Hibernate支持,添加方式和添加Struts一样。在项目右键-myEclipse-Add Hibernate Capabilities,弹出下面对话框,选择Hibernate3.3
按照上面进行设置,然后点击Next
这一步主要是配置文件的名称和路径,如果是新建的那么默认配置就行,然后点击Next
选框取消,然后点击Next
中,所以要创建一个包,这里包名叫:com.dao
Driver and Add to Classpath> 把数据库驱动加入到项目中
3.1 Hibernate配置文件
配置Hibernate.cfg.xml文件主要就是配置数据库方面,下面来看看配置信息:
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"https://www.360docs.net/doc/0213477420.html,/hibernate-configuration-3.0.dtd ">
name="myeclipse.connection.profile">sql2005
jdbc:sqlserver://HH-PC;database=test;
com.microsoft.sqlserver.jdbc.SQLServerDriver
org.hibernate.dialect.SQLServerDialect
其中,dialect参数是必须配置的,用于配置Hibernate使用的不同数据库类型,Hibernate 支持几乎所有的主流数据库,包括Oracle、DB2、Ms Sqlserver、MySql等。Show_sql参数为true,则程序运行时在控制台输出执行的SQL语句。
数据库表和实体的映射信息在另外的映射文件中定义,但需要在配置文件中声明,具体下:
上面的代码表示初始化Hibernate环境时,将装载Tt.hbm.xml映射信息
3.2 实体类和映射文件
在上面,我们配置了映射文件为Tt.hbm.xml,这个文件表示实体类对应的数据库表的各个参数,首先我们需要建立与之对应的实体类Tt
Tt.java
package com.dao;
public class Tt implements java.io.Serializable {
// Fields
private Integer id;
private String name;
public Tt() {
}
public Tt(Integer id) {
this.id = id;
}
public Tt(Integer id, String name) {
this.id = id;
https://www.360docs.net/doc/0213477420.html, = name;
}
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return https://www.360docs.net/doc/0213477420.html,;
}
public void setName(String name) {
https://www.360docs.net/doc/0213477420.html, = name;
}
}
这个实体类实现implements java.io.Serializable接口,然后建立映射文件为这个实体类建立和数据库表的对应关系,映射到数据库中的哪个表,以及哪个表中的哪个字段等。
Tt.hbm.xml
"https://www.360docs.net/doc/0213477420.html,/hibernate-mapping-3.0.dtd">
在映射文件中
3.3 使用代码操作
要使用Hibernate进行数据库操作,需要经过7个步骤:
a)示例1,读取指定序号的姓名,查询单个数据
Configuration config = new Configuration().configure(); SessionFactory fac = config.buildSessionFactory();
Session session = fac.openSession();
Tt t = (Tt) session.get(Tt.class, 1);
System.out.println(t.getName());
session.close();
b)示例2,保存数据
Configuration config = new Configuration().configure();
SessionFactory fac = config.buildSessionFactory();
Session session = fac.openSession();
Transaction tx = session.beginTransaction();
Tt t = new Tt();
t.setName("黄斯于");
session.save(t);
https://www.360docs.net/doc/0213477420.html,mit();
session.close();
System.out.println("save ok...");
单词:Configuration,SessionFactory,Session,Transaction
上述Hibernate对象间执行过程如下:
c)示例3,修改数据
Configuration config = new Configuration().configure();
SessionFactory fac = config.buildSessionFactory();
Session session = fac.openSession();
Transaction tx = session.beginTransaction();
Tt t = (Tt)session.get(Tt.class, 8);
t.setName("黄斯于2");
session.update(t);
https://www.360docs.net/doc/0213477420.html,mit();
session.close();
System.out.println("update ok...");
d)示例4,删除数据
Configuration config = new Configuration().configure();
SessionFactory fac = config.buildSessionFactory();
Session session = fac.openSession();
Transaction tx = session.beginTransaction();
Tt t = (Tt)session.get(Tt.class, 8);
session.delete(t);
https://www.360docs.net/doc/0213477420.html,mit();
session.close();
System.out.println("deleted ok...");
e)示例5,查询所有数据
使用createCriteria来查询特定持久化类的数据,Criteria(条件)。下面代码将表中数据全部查询并放入到集合中。
Configuration config = new Configuration().configure();
SessionFactory fac = config.buildSessionFactory();
Session session = fac.openSession();
java.util.List r=
session.createCriteria(Tt.class).list();
for(Tt o:r){
System.out.println(o.getName());
}
session.close();
System.out.println(" ok...");
1)表示获取5条记录:
java.util.List r=
session.createCriteria(Tt.class).setMaxResults(5).list(); 2)表示获取字段name 姓黄的数据:
java.util.List r=
session.createCriteria(Tt.class).add(Expression.like("name", "黄%")).list();
3.3.1课堂练习1
选择题:
1.下面不属于持久化的是()
A.把对象转换为字符串的形式通过网络传输,在另一端接收到这个字符串后能
把对象还原出来。
B.把程序数据从数据库中读出来
C.从XML配置文件中读取程序的配置信息
D.把程序数据保存为文件
2.下面()不属于关系-对象映射的映射信息
A.程序包名到数据库库名的映射
B.程序类名到数据库表名的映射
C.实体属性名到数据库表字段的映射
D.实体属性类型到数据库表字段类型的映射
3.下面()不是Hiberante映射文件中包含的内容。(选两项)
A.数据库连接信息
B.Hibernate属性参数
C.主键生成策略
D.属性数据类型
4.下面的程序执行后没有报错,但数据总保存不到数据库,最可能的原因是()
Public static void main(String[] args){
SessionFactory sf=new
Configuration().configure().buildSessionFactory();
Session session=sf.openSession();
medal medal=new Medal();
medal.setOwner=”Shen Baozhi”;
medal.setPort(“Table Tennis-Women’s Singles”);
medal.setType(“Gold Medal”);
session.save(user);
session.close();
}
A.配置文件配置有误
B.没有在配置文件中包含对映射文件的声明
C.映射文件配置有误
D.没有对持久化操作捕捉异常
E.没有开启事务
5.依据下面的异常信息(如图),判断问题出现的原因是()
A.映射文件中类名和属性名应该区分大小写
B.映射文件中实体类名应包括包名,如:com.entity.dao.Tt
C.映射文件中表名应该全部小写
D.实体类Tt没有定义
3.3.2课堂练习2
某电子备件管理系统的详细设计文档中有如下数据库表:
备件(编号,型号,FRU编号,工厂,出厂价格,出厂日期,经销商,发票日期,发票价格,保修终止日期,附录)
(1)请根据上述信息创建数据库表,将创建表的SQL脚本写下来。表名和字段名用浅显易懂的英文。“编号”为bigint类型,”FRU编号”为字符型,价格为
money类型,日期为Datetime类型
(2)建立对应的实体类,对应bigint使用Long类型,对应money使用Double 类型,对应日期使用java.sql.Date类型
(3)建立EcrParts.hbm.xml映射文件,正确配置实体到数据库表的映射
提示:使用“编号“字段为主键,”FRU编号”需要在数据库建立唯一约束,在映射文件这种定义unique属性为true
(4)编写程序,使用Hiberante实现如下功能:
A.添加如下备件信息进入数据库
B.更新这条数据,将如下数据更新到数据库
C.删除这条数据
3.4 复习DAO模式,利用DAO模式进行操作
DAO模式的应用主要优势体现在,把和数据库打交道的通用部分另外放到别的地方便于维护和修改。
3.4.1利用Hibernate实现DAO模式
表结构:(表名:tt,id为自动增长列)
使用Hibernate建立一个DAO代码,DAO接口如下。
package com.dao;
import java.util.List;
public interface TtDAO {
public void add(Tt item);//新增
public void del(int tid);//删除
public void update(Tt item);//修改
public List search();//查询所有
}
目标一:实现抽象类,BaseHibernateDAO,完成未完成的代码
package com.dao;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import java.util.List;
public abstract class BaseHibernateDAO {
private Session session=null;//成员变量
protected Object get(Class clz,java.io.Serializable id){ //根据id得到对象
}
protected void add(Object item){
//新增
}
protected void update(Object item){
//修改
}
protected void delete(Class clz,java.io.Serializable id){ //根据id删除对象
}
protected List search(Class clz){
//查询所有数据
}
public void setSession(Session session){
this.session=session;
}
protected Session getSession(){
//得到Session
Configuration config=new Configuration().configure();
SessionFactory fac= config.buildSessionFactory();
this.session=fac.openSession();
return this.session;
}
protected void closeSession(){
//关闭Session
this.session.close();
this.session=null;
}
}
目标二:使用接口和BaseHibernateDAO,实现TtDAOHibImpl类,用来实现具体代码。
根据下面的框架完成未完成的代码。
package com.dao;
import java.util.List;
public class TtDAOHibImpl extends BaseHibernateDAO implements TtDAO {
public void add(Tt item) {
}
public void del(int tid) {
}
public List search() {
}
public void update(Tt item) {
}
}
完成上述未完成的代码,并使用下面示例进行测试
public class test {
public static void main(String[] args) {
// TODO Auto-generated method stub
TtDAOHibImpl dao=new TtDAOHibImpl();
List mylist= dao.search();
for(Tt t:mylist){
System.out.println(t.getName());
}
}
}
3.4.2上机练习1
3.5 Hibernate查询
Hibernate支持两种主要的查询方式:HQL查询和Criteria查询
3.6 HQL
HQL是Hibernate提供的一种面向对象的查询语言,使用HQL可以避免使用JDBC 查询的一些弊端。
要使用HQL需要4步:
(1)得到session
(2)编写HQL语句
(3)创建Query对象
(4)执行查询,得到结果
3.6.1实例一:查询所有数据
TtDAO tdao=new TtDAO();
Session session= tdao.getSession();
Query q= session.createQuery(" from Tt");
List list=q.list();
for(Tt t:list){
System.out.println(t.getName());
}
session.close();
HQL语句为“from Tt”其中Tt并非代表表名,而是类名。其中不需要select,但是如果要有select,那么需要把类名加一个别名:
Select ct from Tt as ct;
3.6.2实例二:高级查询
A.一般查询
TtDAO tdao=new TtDAO();
Session session= tdao.getSession();
Query q= session.createQuery(" from Tt as cf where https://www.360docs.net/doc/0213477420.html, like '%张%'");
List list=q.list();
for(Tt t:list){
System.out.println(t.getName());
}
session.close();
要进行模糊查询,HQL语句支持Where子句,支持like关键字,也支持%通配符,不过查询的时候类名要有个别名。支持:
Where,like,%,>=,>,<,<=<>,(,),is null,and ,or,not,in,between等
from Tt as cf where https://www.360docs.net/doc/0213477420.html, like '%张%'
B.预处理查询
问题:如果不写别名会怎样?
如果这样拼装HQL语句容易带来安全隐患(SQL注入攻击),有类似PreparedStatement 的做法吗?
TtDAO tdao = new TtDAO();
Session session = tdao.getSession();
String hql=" from Tt as cf where https://www.360docs.net/doc/0213477420.html, like ?";
Query q = session.createQuery(hql);
q.setString(0, "%张%");
List list = q.list();
for (Tt t : list) {
System.out.println(t.getName());
}
session.close();
注意:在运行上述代码的时候,会出现
https://www.360docs.net/doc/0213477420.html,ng.NoSuchMethodError: antlr.collections.AST.getLine()I 这种错误,错误原因是struts和hibernate3.3中的jar包冲突,解决办法:
1) 关闭MyEclipse
2) 在MyEclipse的Common\plugins目录中搜索 *struts*.jar总共有3个jar包,找到其中
3) com.genuitec.eclipse.cross.easystruts.eclipse_8.5.0.me201003101716.jar
4) 用winRAR之类的软件将其打开,删除lib或者data下的antlr-2.7.2.jar文件。
如果2,3,4无效,可用下面方式:
a) 在My Eclipse的conf iguration\org.eclipse.osgi\bundles目录下搜索antlr-2.7.2.jar,删除所有antlr-2.7.2的jar包文
件;
b) 在My Eclipse的Common\plugins目录中搜索 *struts*.jar总共有3个jar包,用winRAR之类的软件将其打开,删除
lib或者data下的antlr-2.7.2.jar文件。
5) 打开MyEclipse,删除Struts 2 core libraries,然后重新添加
移除,并点击Add Library
点击下一步,然后重新选择Struts 2 core libraries添加即可。
C.指定多表查询