第二章 Hibernate入门
一 Hello例子:
1、 创建数据库:
create table CUSTOMERS(
ID bigint not null primary key,
NAME varchar(15) not null,
EMAIL varchar(128)not null,
PASSWORD varchar(8)not null,
PHONE int,
ADDRESS varchar(255),
SEX char(1),
IS_MARRIED bit,
DESCRIPTION text,
IMAGE blob,
BIRTHDAY date,
REGISTERED_TIME timestamp
);
2、映射文件
Customers.hbm.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">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<class name="vo.Customers" table="customers" catalog="weiqintest">
<id name="id" type="long">
<column name="ID" />
<generator class="increment" />
</id>
<property name="name" type="string">
<column name="NAME" length="15" not-null="true" />
</property>
<property name="email" type="string">
<column name="EMAIL" length="128" not-null="true" />
</property>
<property name="password" type="string">
<column name="PASSWORD" length="8" not-null="true" />
</property>
<property name="phone" type="int">
<column name="PHONE" />
</property>
<property name="address" type="string">
<column name="ADDRESS" />
</property>
<property name="sex" type="character">
<column name="SEX" length="1" />
</property>
<property name="Married" type="boolean">
<column name="IS_MARRIED" />
</property>
<property name="description" type="text">
<column name="DESCRIPTION" length="65535" />
</property>
<property name="image" type="binary">
<column name="IMAGE" />
</property>
<property name="birthday" type="date">
<column name="BIRTHDAY" length="10" />
</property>
<property name="registeresTime" type="timestamp">
<column name="REGISTERED_TIME" length="19" not-null="false" />
</property>
</class>
</hibernate-mapping>
3 java类文件
Customers.java
package vo;
import java.sql.Timestamp;
import java.util.Date;
import java.io.Serializable;
/**
* Customers generated by MyEclipse Persistence Tools
*/
public class Customers implements Serializable {
private long id;
private String name;
private String email;
private String password;
private int phone;
private boolean married;
private String address;
private char sex;
private String description;
private byte[] image;
private Date birthday;
private Timestamp registeresTime;
public Customers() {
// TODO Auto-generated constructor stub
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public byte[] getImage() {
return image;
}
public void setImage(byte[] image) {
this.image = image;
}
public boolean getMarried() {
return married;
}
public void setMarried(boolean married) {
this.married = married;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getPhone() {
return phone;
}
public void setPhone(int phone) {
this.phone = phone;
}
public Timestamp getRegisteresTime() {
return registeresTime;
}
public void setRegisteresTime(Timestamp registeresTime) {
this.registeresTime = registeresTime;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
}
小结1
主要学习 数据库类型 java类型 Hibernate类型的对应关系,此处的type为Hibernate的类型。
在映射时最好使用Hibernate类型,因为他和数据库的类项一致,而java类型出入较大。
字段 意义 数据库类型 hibernate类型 java类型
Id 主键(increment) bigint long java.lang.Long
Name 姓名 varchar(15) string java.lang.String
Phone 电话 int int java.lang.Integer
Sex 性别 char(1) character java.lang.String
Ismarried 婚否 bit Boolean java.lang.Boolean//
Description 描述 text string java.lang.String
Image 头像 blob binary java.lang.String
Birthday 出生年月 date date java.Util.Date
RegistedTime 注册时间 timestamp timestamp java.Util.Date
相关知识:
Hibernate映射类型:
在对象-关系映射文件中,Hibernate映射类型作为Java类型和SQL类型的桥梁。在映射文件中建议使用Hibernate映射类型。
2.1. java基本映射类型的Hibernate映射类型:
Java类型、Hibernate映射类型以及SQL类型之间的对应关系:
Java类型 Hibernate映射类型 标准SQL类型
int或java.lang.Integer integer或int INTEGER
long或java.lang.Long long BIGINT
short或java.lang.Short short SMALLINT
byte或java.lang.Byte byte TINYINT
float或java.lang.Float float FLOAT
double或java.lang.Double double DOUBLE
java.math.BigDecimal big_decimal NUMERIC
char或java.lang.Character character CHAR(1)
java.lang.String string VARCHAR
boolean或java.lang.Boolean boolean BIT
boolean或java.lang.Boolean yes_no CHAR(1)('Y'或' N')
boolean或java.lang.Boolean true_false CHAR(1)('T'或' F')
2.2. java时间和日期类型的Hibernate映射类型:
Java类型 Hibernate映射类型 标准SQL类型 说明
java.util.Date或java.sql.Date date DATE 日期
java.util.Date或java.sql.Time time TIME 时间
java.util.Date或java.sql.Timestamp timestamp TIMESTAMP 时间戳
java.util.Calendar calendar TIMESTAMP
java.util.Calendar calendar_date DATE
2.3. java大对象类型的Hibernate映射类型:
Java类型 Hibernate映射类型 标准SQL类型 MySQL类型 Oracle类型
byte[] binary VARBINARY(或者BLOB) BLOB BLOB
java.lang.String text CLOB TEXT CLOB
实现java.io.Serializable接口的任意一个java类 serializable VARBINARY(或者BLOB) BLOB BLOB
java.sql.Clob clob CLOB TEXT CLOB
java.sql.Blob blob BLOB BLOB BLOB
4、使用Myeclipse自动生成的SessionFactory,它的责任是解析hibernate的配置文件以及映射文件,提供唯一的SessionFactory对象,(SessionFactory对象用于随时获得Session对象实例)。
HibernateSessionFactory.java
package vo;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
/**
* Configures and provides access to Hibernate sessions, tied to the
* current thread of execution. Follows the Thread Local Session
* pattern, see {@link http://hibernate.org/42.html }.
*/
public class HibernateSessionFactory {
/**
* Location of hibernate.cfg.xml file.
* Location should be on the classpath as Hibernate uses
* #resourceAsStream style lookup for its configuration file.
* The default classpath location of the hibernate config file is
* in the default package. Use #setConfigFile() to update
* the location of the configuration file for the current session.
*/
private static String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml";
private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
private static Configuration configuration = new Configuration();
private static org.hibernate.SessionFactory sessionFactory;
private static String configFile = CONFIG_FILE_LOCATION;
static {
try {
configuration.configure(configFile);
sessionFactory = configuration.buildSessionFactory();
} catch (Exception e) {
System.err
.println("%%%% Error Creating SessionFactory %%%%");
e.printStackTrace();
}
}
private HibernateSessionFactory() {
}
/**
* Returns the ThreadLocal Session instance. Lazy initialize
* the <code>SessionFactory</code> if needed.
*
* @return Session
* @throws HibernateException
*/
public static Session getSession() throws HibernateException {
Session session = (Session) threadLocal.get();
if (session == null || !session.isOpen()) {
if (sessionFactory == null) {
rebuildSessionFactory();
}
session = (sessionFactory != null) ? sessionFactory.openSession()
: null;
threadLocal.set(session);
}
return session;
}
/**
* Rebuild hibernate session factory
*
*/
public static void rebuildSessionFactory() {
try {
configuration.configure(configFile);
sessionFactory = configuration.buildSessionFactory();
} catch (Exception e) {
System.err
.println("%%%% Error Creating SessionFactory %%%%");
e.printStackTrace();
}
}
/**
* Close the single hibernate session instance.
*
* @throws HibernateException
*/
public static void closeSession() throws HibernateException {
Session session = (Session) threadLocal.get();
threadLocal.set(null);
if (session != null) {
session.close();
}
}
/**
* return session factory
*
*/
public static org.hibernate.SessionFactory getSessionFactory() {
return sessionFactory;
}
/**
* return session factory
*
* session factory will be rebuilded in the next call
*/
public static void setConfigFile(String configFile) {
HibernateSessionFactory.configFile = configFile;
sessionFactory = null;
}
/**
* return hibernate configuration
*
*/
public static Configuration getConfiguration() {
return configuration;
}
}
5、对数据库进行增删改查的DAO类。
BusinessService.java
package vo;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.sql.Date;
import java.util.Iterator;
import java.util.List;
import javax.servlet.ServletContext;
import javax.servlet.ServletOutputStream;
//import org.hibernate.Session;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.Session;
public class BusinessService {
public static SessionFactory sf = HibernateSessionFactory
.getSessionFactory();
/*
* 查询所有的Customers对象,然后调用 printCustomers()方法打印Customers对象信息
*/
public void findAllCustomers(ServletContext context, OutputStream out) {
Session session = null;
Transaction tx = null;
try {
session = sf.openSession();
tx = session.beginTransaction();
List list = (List) session.createQuery(
"from Customers as c order by c.name asc").list();
for (Iterator it = list.iterator(); it.hasNext();) {
printCustomers(context, out, (Customers) it.next());
}
tx.commit();
} catch (Exception e) {
// TODO: handle exception
if (tx != null) {
tx.rollback();
}
e.printStackTrace();
} finally {
session.close();
}
}
/*
* 持久化一个Customers对象
*/
public void saveCustomer(Customers Customers) {
Session session = null;
Transaction tx = null;
try {
session = sf.openSession();
tx = session.beginTransaction();
session.save(Customers);
tx.commit();
} catch (Exception e) {
// TODO: handle exception
if (tx != null) {
tx.rollback();
}
e.printStackTrace();
} finally {
session.close();
}
}
/*
* 按照OID加载一个Customers对象,然后修改它的属性
*/
public void loadAndUpdateCustomer(long Customers_id, String address) {
Session session = null;
Transaction tx = null;
try {
session = sf.openSession();
tx = session.beginTransaction();
Customers Customers = (Customers) session.load(Customers.class,
Customers_id);
Customers.setAddress(address);
tx.commit();
} catch (Exception e) {
// TODO: handle exception
if (tx != null) {
tx.rollback();
}
e.printStackTrace();
} finally {
session.close();
}
}
/*
* 删除所有的Customers对象
*/
public void deleteAllCustomers() {
Session session = null;
Transaction tx = null;
try {
session = sf.openSession();
tx = session.beginTransaction();
Query q = session.createQuery("delete Customers");
q.executeUpdate();
tx.commit();
} catch (Exception e) {
// TODO: handle exception
if (tx != null) {
tx.rollback();
}
e.printStackTrace();
} finally {
session.close();
}
}
/*
* 选择向控制台还是动态网页输出Customers对象的信息
*/
private void printCustomers(ServletContext context, OutputStream out,
Customers customer) throws Exception {
if (out instanceof ServletOutputStream)
printCustomer(context, (ServletOutputStream) out, customer);
else
printCustomer((PrintStream) out, customer);
}
/*
* 把Customers对象的信息输出到控制台,入Dos控制台
*/
private void printCustomer(PrintStream out, Customers customer)
throws Exception {
// save photo
byte[] buffer = customer.getImage();
FileOutputStream fout = new FileOutputStream("photo_copy.gif");
fout.write(buffer);
fout.close();
out.println("------以下是" + customer.getName() + "的个人信息------");
out.println("ID: " + customer.getId());
out.println("口令: " + customer.getPassword());
out.println("E-Mail: " + customer.getEmail());
out.println("电话: " + customer.getPhone());
out.println("地址: " + customer.getAddress());
String sex = customer.getSex() == 'M' ? "男" : "女";
out.println("性别: " + sex);
String marriedStatus = customer.getMarried() ? "已婚" : "未婚";
out.println("婚姻状况: " + marriedStatus);
out.println("生日: " + customer.getBirthday());
out.println("注册时间: " + customer.getRegisteresTime());
out.println("自我介绍: " + customer.getDescription());
}
/*
* 把Customers对象的信息输出到动态网页
*/
private void printCustomer(ServletContext context, ServletOutputStream out,
Customers customer) throws Exception {
// save photo
byte[] buffer = customer.getImage();
String path = context.getRealPath("/");
FileOutputStream fout = new FileOutputStream(path + "photo_copy.gif");
fout.write(buffer);
fout.close();// 生成 photo_copy.gif
out.println("------以下是" + customer.getName() + "的个人信息------" + "<br>");
out.println("ID: " + customer.getId() + "<br>");
out.println("口令: " + customer.getPassword() + "<br>");
out.println("E-Mail: " + customer.getEmail() + "<br>");
out.println("电话: " + customer.getPhone() + "<br>");
out.println("地址: " + customer.getAddress() + "<br>");
String sex = customer.getSex() == 'M' ? "男" : "女";
out.println("性别: " + sex + "<br>");
String marriedStatus = customer.getMarried() ? "已婚" : "未婚";
out.println("婚姻状况: " + marriedStatus + "<br>");
out.println("生日: " + customer.getBirthday() + "<br>");
out.println("注册时间: " + customer.getRegisteresTime() + "<br>");
out.println("自我介绍: " + customer.getDescription() + "<br>");
out.println("<img src='photo_copy.gif' border=0><p>");
// shi
out.flush();
out.close();
}
public void test(ServletContext context, OutputStream out) throws Exception {
Customers customer = new Customers();
customer.setName("Tom");
customer.setEmail("tom@yahoo.com");
customer.setPassword("1234");
customer.setPhone(55556666);
customer.setAddress(" Shanghai ");
customer.setSex('M');
customer.setDescription("I am very honest.");
InputStream in = this.getClass().getResourceAsStream("photo.gif");
byte[] buffer = new byte[in.available()];
in.read(buffer);
customer.setImage(buffer);
customer.setBirthday(Date.valueOf(" 1980-05-06 "));
saveCustomer(customer);
findAllCustomers(context, out);
loadAndUpdateCustomer(customer.getId(), " Beijing ");
findAllCustomers(context, out);
deleteAllCustomers();
}
public static void main(String[] args) throws Exception {
new BusinessService().test(null, System.out);
sf.close();
}
}
小结2
我在调试中遇到的问题是,我用的是Hibernate3.0,而书上是以2.0为例的,所以有些方法不能使。如:在删除所有记录时,2.0中有session.dlelete(String str)方法,3.0中是session.dlelete(Object obj),我改成了
Query q = session.createQuery("delete Customers");
q.executeUpdate();
这个例子的另一个新颖的地方就是,我们可以根据传入的 OutputStream 的具体类型,来决定是输出到动态网页中 还是输出到控制台:
private void printCustomers(ServletContext context, OutputStream out,
Customers customer) throws Exception {******}
其中的test方法:先添加一个Customers 对象,然后输出,最后删除。
如果是输出到控制台,就在工程的根目录下产生photo.gif的副本
如果是输出到网页中,就在部署到tomcat后的工程的根目录下生成photo.gif的副本
6、servlet类 调用BusinessService的test方法
package service;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import vo.BusinessService;
public class DBServlet extends HttpServlet {
public DBServlet() {
super();
}
public void destroy() {
super.destroy(); // Just puts "destroy" string in log
// Put your code here
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
new BusinessService().test(this.getServletContext(), response
.getOutputStream());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void init() throws ServletException {
// Put your code here
}
}
7 、web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app PUBLIC
'-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN'
'http://java.sun.com/j2ee/dtds/web-app_2_3.dtd'>
<web-app>
<servlet>
<servlet-name>DBServlet</servlet-name>
<servlet-class>service.DBServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DBServlet</servlet-name>
<url-pattern>/DBServlet</url-pattern>
</servlet-mapping>
</web-app>
8、jsp页面
Hello.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<html>
<head>
<title>hello</title>
</head>
<body>
<jsp:forward page="DBServlet" />
</body>
</html>