hibernate是对jdbc的封装,是对在项目中持久层的操作,有利于程序员将业务逻辑和对数据库的持久化操作分开来,在数据库中表都是关系间的映射,而在hibernate中,将表之间的映射转化为了在关系间的映射,有利于开发人员的分层逻辑
首先 我们要在项目中配置hibernate的配置文件 ,在hibernate初始化的时候 就要先加载配置文件到configuration实例 由于我的eclipse没有搭载hibernate的开发环境 因此还是手动在src的目录下创建一个xml文件 约定俗称为hibernate.cfg.xml
具体信息如下
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<!--声明Hibernate配置文件的开始-->
<hibernate-configuration>
<!--表明以下的配置是针对session-factory配置的,SessionFactory是Hibernate中的一个类,这个类主要负责保存HIbernate的配置信息,以及对Session的操作-->
<session-factory>
<!--配置数据库的驱动程序,Hibernate在连接数据库时,需要用到数据库的驱动程序-->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver </property>
<!--设置数据库的连接url:jdbc:mysql://localhost/hibernate,其中localhost表示mysql服务器名称,此处为本机, hibernate是数据库名-->
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hbdemo </property>
<!--连接数据库是用户名-->
<property name="hibernate.connection.username">root </property>
<!--连接数据库是密码-->
<property name="hibernate.connection.password"></property>
<!--数据库连接池的大小-->
<property name="hibernate.connection.pool.size">20 </property>
<!--是否在后台显示Hibernate用到的SQL语句,开发时设置为true,便于差错,程序运行时可以在Eclipse的控制台显示Hibernate的执行Sql语句。项目部署后可以设置为false,提高运行效率-->
<property name="hibernate.show_sql">true </property>
<!--jdbc.fetch_size是指Hibernate每次从数据库中取出并放到JDBC的Statement中的记录条数。Fetch Size设的越大,读数据库的次数越少,速度越快,Fetch Size越小,读数据库的次数越多,速度越慢-->
<property name="jdbc.fetch_size">50 </property>
<!--jdbc.batch_size是指Hibernate批量插入,删除和更新时每次操作的记录数。Batch Size越大,批量操作的向数据库发送Sql的次数越少,速度就越快,同样耗用内存就越大-->
<property name="jdbc.batch_size">23 </property>
<!--jdbc.use_scrollable_resultset是否允许Hibernate用JDBC的可滚动的结果集。对分页的结果集。对分页时的设置非常有帮助-->
<property name="jdbc.use_scrollable_resultset">false </property>
<!--connection.useUnicode连接数据库时是否使用Unicode编码-->
<property name="Connection.useUnicode">true </property>
<!--connection.characterEncoding连接数据库时数据的传输字符集编码方式,最好设置为gbk,用gb2312有的字符不全-->
<property name="connection.characterEncoding">utf-8 </property>
<property name="hibernate.current_session_context_class">thread</property>
<!--hibernate.dialect 只是Hibernate使用的数据库方言,就是要用Hibernate连接那种类型的数据库服务器。-->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect </property>
<!--指定映射文件为“hibernate/ch1/UserInfo.hbm.xml”-->
<mapping resource="com/kevinswift/entity/User.hbm.xml"/>
<!-- <mapping resource="com/kevinswift/entity/address.hbm.xml"/> -->
<!-- 使用的是本地事务 -->
</session-factory>
</hibernate-configuration>
其中在hibernate-configuration配置的就是hibernate的一些属性 比较重要的有
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver </property>
配置数据库的驱动
<!--设置数据库的连接url:jdbc:mysql://localhost/hibernate,其中localhost表示mysql服务器名称,此处为本机, hibernate是数据库名-->
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hbdemo </property>
设置数据库的url地址 这里是在本地的3306接口下的hbdemo数据库
<!--连接数据库是用户名-->
<property name="hibernate.connection.username">root </property>
<!--连接数据库是密码-->
<property name="hibernate.connection.password"></property>
登录本地数据库时候的密码和 <property name="hibernate.show_sql">true </property>
账号
<property name="hibernate.show_sql">true </property>
是否在后台显示sql语句等
详细的请参考这个博客
http://blog.youkuaiyun.com/qiaqia609/article/details/9456489/
随后我们可以在数据库中创建一个user表
在user表中有id,type,password,name属性
我们在com.kevinswift.entity包下创建一个JavaBean约定和表名一样
User.java 这个类中有表名的各个属性 随后生成getter和setter方法,和默认的共有的构造方法User()
package com.kevinswift.entity;
public class User implements java.io.Serializable{
//user的属性
private int id;
private String name;
private String password;
private String type;
private address add;
public address getAdd() {
return add;
}
public void setAdd(address add) {
this.add = add;
}
//javaBean的默认构造方法 实现java的反射机制
public User() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
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 String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
随后再com.kevinswift.entity下创建个表名一起的映射文件 约定为User.hbm.xml文件 里面表示映射User类和xml文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- name指定持久化类的类名 table指定数据表的名称 -->
<hibernate-mapping>
<class name = "com.kevinswift.entity.User" table = "user">
<!-- user类中的id 指定为数据表中的id 为主键-->
<id name = "id" type = "java.lang.Integer" column = "id">
<!-- 关联持久化类的属性名 -->
</id>
<!-- name属性 -->
<property name = "name" type = "java.lang.String" column = "name" length = "80"/>
<property name = "type" type = "java.lang.String" column = "type" length = "80"/>
<property name = "password" type = "java.lang.String" column = "password" length = "80"/>
</class>
<!-- 基于主键的一对一模式 -->
</hibernate-mapping>
class代表是加载哪个类和数据库中的哪个表进行映射 随后id表示主键名,随后property 表示各个属性的名字 这样就把user类中的各个字段和table表中进行了映射
要记住在hibernate.cfg.xml文件的Mapping元素中加载这个mapping文件
随后加载驱动类 hibernateUtil.java文件 创建一个或多个ssession 负责hibernate的启动,也负责完成存储和访问sessionFactory的操作,
package com.kevinswift.entity;
import java.io.File;
import org.hibernate.*;
import org.hibernate.cfg.*;
import org.hibernate.service.*;
import org.hibernate.boot.registry.*;
/**
* Description:
* @author VipMao
* @version 1.0
*/
/**
* 该工具类提供了一个属性:SessionFactory sessionFactory
* 并创建了sessionFactory 将它设置成static 这样其他程序就可以直接通过此工具类引用
* 提供了二个方法:
* 1:通过线程创建Session-->currentSession()
* 2:关闭Session-->closeSession()
* 需要在主类中手动关闭sessionFactory
*/
public class HibernateUtil
{
public static final SessionFactory sessionFactory;
//创建sessionFactory
static
{
try
{
// 采用默认的hibernate.cfg.xml来启动一个Configuration的实例
//还可以通过文件的路径名字来进行读取
Configuration cfg = new Configuration()
.configure();
// 以Configuration实例来创建SessionFactory实例
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
.applySettings(cfg.getProperties()).build();
sessionFactory = cfg.buildSessionFactory(serviceRegistry);
}
catch (Throwable ex)
{
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
// ThreadLocal可以隔离多个线程的数据共享,因此不再需要对线程同步
public static final ThreadLocal<Session> session
= new ThreadLocal<Session>();
//创建Session
public static Session currentSession()
throws HibernateException
{
//通过线程对象.get()方法安全创建Session
Session s = session.get();
// 如果该线程还没有Session,则创建一个新的Session
if (s == null)
{
s = sessionFactory.openSession();
// 将获得的Session变量存储在ThreadLocal变量session里
session.set(s);
}
return s;
}
//关闭Session
public static void closeSession()
throws HibernateException
{
Session s = session.get();
if (s != null)
s.close();
session.set(null);
}
}
首先是通过bew configuration().confige来读取配置文件hibernate.cfg.xml随后创建sessionFactory的实例sessionFacroty实例是全局唯一的,对应着应用程序的数据源,通过SessionFactory来获得多个session的实例,可以比喻为session的实例工厂,而且sessionFactory默认是线程安全的,在应用程序中默认只创建一个
随后编写接口类UserDao类,DAO设计模式将底层的数据访问逻辑和上层的业务逻辑分开,这样可以更加专注于数据访问代码的编写规范
DAO模式需要以下几个组件
一个是DAO接口 定义了用户的操作 写的都是抽象的方法
一个是实现DAO接口的具体类 实现DAO接口,当然就是实现DAO接口中的所有抽象方法
package com.kevinswift.dao;
import java.util.*;
import org.hibernate.*;
import com.kevinswift.entity.*;
public interface UserDAO {
//添加用户
void save(User user);
//根据用户id表示指定查找用户
User findById(int id);
//删除用户
void delete(User user);
//修改用户信息
void update(User user);
void query();
}
一个是DAO工厂类
当用户需要添加新的操作方法时,只需在DAO实现类中添加新的方法即可
随后定义DAOd的实现类UserDAOImpl接口
package com.kevinswift.dao;
import java.awt.List;
import java.util.Collection;
import org.hibernate.*;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.Restrictions;
import com.kevinswift.entity.*;
public class UserDAOImpl implements UserDAO {
public void save(User user) {
// TODO Auto-generated method stub
//生成session的对象
Session session = HibernateUtil.currentSession();
//创建transaction实例 以事务的开始为边界
Transaction tx = session.beginTransaction();
try {
//save方法保存到数据库
session.save(user);
//get方法是通过标识符得到指定类的持久化对象
//获取userid为123456的持久化对象
User us = (User) session.get(User.class, "123456");
//createQuery来进行查询
//createSQLquery建立sqlquery来查询接口的实力
// Collection stu = session.createFilter(arg0, arg1)
//List use = session.createSQLQuery("select {user.*} from user {user}","user",User.class);
//HQL语言进行查询事务
//HQL检索方式 QBC检索凡是 SQL检索方式
//创建query实例 根据名称来设置
Query query = session.createQuery("from user where age > :userAge");
//根据名称设置integer的参数
query.setInteger("userAge", 25);
//根据位置来设置
Query qu = session.createQuery("from user where age > ?");
//根据位置来设置 第一参数的位置为0
qu.setInteger(0, 25);
//随后进行取出 q
//提交事务
tx.commit();
} catch (Exception e) {
// TODO: handle exception
//回滚事务
e.printStackTrace();
tx.rollback();
}
finally {
//关闭session
HibernateUtil.closeSession();
}
}
public void query() {
Session session = HibernateUtil.currentSession();
//创建transaction实例 以事务的开始为边界
Transaction tx = session.beginTransaction();
Query query = session.createQuery("from user id > ?");
query.setInteger(0, 50);
List user = (List) query.list();
System.out.println(user.getSelectedIndex());
}
public User findById(int id) {
User user = null;
Session session = HibernateUtil.currentSession();
Transaction tx = session.beginTransaction();
// TODO Auto-generated method stub
return null;
}
public void delete(User user) {
// TODO Auto-generated method stub
}
public void update(User user) {
// TODO Auto-generated method stub
}
负责实现DAO接口的所有抽象方法
随后核心的是生成一个个session会话信息就是与数据库之间的交流,创建transcation实例,
通过session.save方法 来保存实例 提交事务 当保存发生错误时候,此时就要回滚事务
编写测试类 我们通常需要在程序中编写测试类,将Junit包加载到项目中,随后创建test类
填写要测试的类和类中的方法
import static org.junit.Assert.*;
import org.junit.Test;
import com.kevinswift.dao.*;
import com.kevinswift.dao.UserDAOImpl;
import com.kevinswift.entity.HibernateUtil;
import com.kevinswift.entity.User;
import com.kevinswift.entity.address;
import org.hibernate.*;
import org.junit.*;
import com.kevinswift.*;
public class testYser {
@Before //注解表明是setUp的方法
public void setUp() throws Exception {
}
@Test
public void testSave() {
UserDAO userdao = new UserDAOImpl();
try {
User u = new User();
u.setId(102);
u.setName("aaa");
u.setPassword("123");
u.setType("ccc");
userdao.save(u);
Session session = HibernateUtil.currentSession();
//session.save(add);
session.update(u);
Transaction tx = session.beginTransaction();
tx.commit();
} catch (Exception e) {
// TODO: handle exception
}
fail("Not yet implemented");
}
这样即可完成测试 @test是注解的意思 可以看见后台成功打印数据和数据的成功插入 整个目录结构如下