Hibernate框架基础——Hibernate入门
Hibernate入门
Hibernate介绍
Hibernate是一个基于jdbc的开源的持久化框架,是一个优秀的ORM实现,它很大程度的简化了dao层编码工作。Hibernate对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。
在分层结构中处于持久化层,封装对数据库的访问细节,使业务逻辑层更专注于实现业务逻辑。
Hibernate的主页为:http://www.hibernate.org/。
Hibernate的下载地址为:http://hibernate.org/orm/downloads/。
HibernateTools的下载地址为:http://www.jboss.org/tools/download/。在Eclipse中如何安装Hibernate Tools插件,请参看Eclipse在线配置Hibernate Tools。
本人使用的是hibernate-release-4.3.11.Final。
Hibernate的体系结构与开发步骤
Hibernate的体系结构:
Hibernate开发步骤
- 创建持久化类
- 创建对象-关系映射文件
- 创建Hibernate配置文件
- 通过Hibernate API编写访问数据库的代码
第一个Hibernate程序(HelloWorld)
创建Eclipse工程并引入相关的jar包
新建Java工程,并添加如下jar包:
- {hibernate_home}/lib/required/*.jar
- 数据库对应的JDBC驱动(例如mysql-connector-java-5.1.38-bin.jar)
还可以加入日志相关的jar包(不加也可以):
- log4j-1.x.x.jar
- slf4j-log4j12-1.x.x.jar
创建持久化对象:User.java
在cn.itcast.a_helloworld包下创建User类,代码如下:
/*** 实体*/
public class User {private int id;private String name;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;}@Overridepublic String toString() {return "[User: id=" + id + ", name=" + name + "]";}}
创建对象-关系映射文件:User.hbm.xml
首先在MySQL数据库里面创建一个t_user表,建表语句如下:
create database hibernate_20160926 default character set utf8;
use hibernate_20160926;
create table t_user( id int primary key auto_increment, name varchar(20) );
t_user表创建好之后,我们就要创建相对应的对象-关系映射文件:User.hbm.xml了,注意该映射配置文件与User类要在一起,即同一个包下。
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC"-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping package="cn.itcast.a_helloworld"><class name="User" table="t_user"><id name="id" type="int" column="id"><generator class="native"/></id><property name="name" type="string" column="name" /></class>
</hibernate-mapping>
关于此映射配置文件中的内容后面会慢慢详解。
创建Hibernate配置文件:hibernate.cfg.xml
我们要在类路径下(即src目录下)创建Hibernate配置文件——hibernate.cfg.xml。
初学者第一次学习Hibernate框架,肯定是不知道如何编写Hibernate配置文件的,但我们可以在{hibernate_home}/project/etc目录下找到开发包给我们提供的Hibernate配置文件,我们只须要拷贝进我们的项目,然后修修改改就可以了。
这样我们的Hibernate配置文件——hibernate.cfg.xml的内容就为:
<!DOCTYPE hibernate-configuration PUBLIC"-//Hibernate/Hibernate Configuration DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"><hibernate-configuration><session-factory name="foo"><!-- 1. 配置数据库信息 --><!-- 方言(连接的数据库类型) --><property name="dialect">org.hibernate.dialect.MySQLDialect</property><property name="connection.url">jdbc:mysql:///hibernate_20160926</property><property name="connection.driver_class">com.mysql.jdbc.Driver</property><property name="connection.username">root</property><property name="connection.password">yezi</property><!-- 2. 其他配置 --><!-- 显示生成的SQL语句 --><property name="hibernate.show_sql">true</property><!-- 3. 导入映射文件 --><mapping resource="cn/itcast/a_helloworld/User.hbm.xml" /></session-factory>
</hibernate-configuration>
关于此配置文件中的内容后面会慢慢详解。
通过Hibernate API编写访问数据库的代码
编程步骤:
- 获取Configuration对象
- 获取SessionFactory对象
- 获取Session,打开事务
- 用面向对象的方式操作数据库
- 关闭事务,关闭Session
由于是Hibernate入门,所以我不会搞得很复杂,就只是简单的向hibernate_20160926数据库中的t_user表中插入一条记录,然后再取出来而已。
我们在cn.itcast.a_helloworld包下创建一个App类,为了方便测试,我使用的是单元测试。
public class App {private static SessionFactory sessionFactory;static {Configuration cfg = new Configuration();cfg.configure("hibernate.cfg.xml"); // 读取指定的主配置文件sessionFactory = cfg.buildSessionFactory(); // 根据配置生成Session工厂}@Testpublic void testSave() {User user = new User();user.setName("张三");// 保存Session session = sessionFactory.openSession(); // 打开一个新的SessionTransaction tx = session.beginTransaction(); // 开启事务session.save(user);tx.commit(); // 提交事务session.close(); // 关闭Session,释放资源(不一定是真正的关闭)}@Testpublic void testGet() {Session session = sessionFactory.openSession();Transaction tx = session.beginTransaction();User user = (User) session.get(User.class, 1); // 获取?System.out.println(user);tx.commit();session.close();}
}
测试第一个Hibernate程序
编写完第一个Hibernate程序之后,我们就要来测试了,先测试向hibernate_20160926数据库中的t_user表中插入一条记录,发现报如下异常:
org.hibernate.engine.jndi.JndiException: Error parsing JNDI name [foo]at org.hibernate.engine.jndi.internal.JndiServiceImpl.parseName(JndiServiceImpl.java:141)at org.hibernate.engine.jndi.internal.JndiServiceImpl.bind(JndiServiceImpl.java:157)at org.hibernate.internal.SessionFactoryRegistry.addSessionFactory(SessionFactoryRegistry.java:103)at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:497)at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1859)at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1930)at cn.itcast.a_helloworld.App.<clinit>(App.java:16)at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)at java.lang.reflect.Constructor.newInstance(Unknown Source)at org.junit.runners.BlockJUnit4ClassRunner.createTest(BlockJUnit4ClassRunner.java:217)at org.junit.runners.BlockJUnit4ClassRunner$1.runReflectiveCall(BlockJUnit4ClassRunner.java:266)at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)at org.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:263)at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)at org.junit.runners.ParentRunner.run(ParentRunner.java:363)at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initialat javax.naming.spi.NamingManager.getInitialContext(Unknown Source)at javax.naming.InitialContext.getDefaultInitCtx(Unknown Source)at javax.naming.InitialContext.getURLOrDefaultInitCtx(Unknown Source)at javax.naming.InitialContext.getNameParser(Unknown Source)at org.hibernate.engine.jndi.internal.JndiServiceImpl.parseName(JndiServiceImpl.java:135)... 28 more
错误原因:
在hibernate.cfg.xml文件内容的配置
<session-factory name="foo">
...
</session-factory>
中添加了name属性。
解决办法:
去掉
<session-factory name="foo">
...
</session-factory>
中的name属性。
修改之后,测试,通过,大发!
第二个Hibernate程序——完整的数据库操作(CRUD)
前面我们写了一个Hibernate入门的小程序,但也只是简单的向hibernate_20160926数据库中的t_user表中插入一条记录,然后再取出来而已。现在我们来写第二个Hibernate程序——实现对数据库完整的操作(CRUD)。
我们首先在cn.itcast.b_dao包下创建一个工具类——HibernateUtils.java,该工具类的作用专门用来获取全局唯一的SessionFactory,以及从全局唯一的SessionFactory中打开一个Session。
public class HibernateUtils {// SessionFactory全局只需要有一个就可以了,因为它的创建和销毁需要消耗大量的资源,初始化信息会比较多,并且它是线程安全的,可以在多线程的环境下使用它private static SessionFactory sessionFactory;static {// 初始化SessionFactory方式一:/*Configuration cfg = new Configuration(); // 代表配置文件的一个对象cfg.configure(); // 读取默认的配置文件(hibernate.cfg.xml)// cfg.configure("hibernate.cfg.xml"); // 读取指定位置的配置文件sessionFactory = cfg.buildSessionFactory();*/// 初始化SessionFactory方式二:sessionFactory = new Configuration() //.configure() //.buildSessionFactory(); // 方法链}/*** 获取全局唯一的SessionFactory* * @return*/public static SessionFactory getSessionFactory() {return sessionFactory;}/*** 从全局唯一的SessionFactory中打开一个Session* * @return*/public static Session openSession() {return sessionFactory.openSession();}}
思考一个问题,若我们要编写代码实现对数据库完整的操作,那么就必定涉及到分页查询,要实现分页查询,我们一定要弄清楚分页设计结构图,要是有人不知道,可翻阅我的记录客户关系管理系统之分页查询。所以我们还要在cn.itcast.b_dao包下创建一个类——QueryResult.java,用于封装查询结果。
public class QueryResult {private int count; // 总记录数private List list; // 一页的数据public QueryResult(int count, List list) {this.count = count;this.list = list;}public int getCount() {return count;}public void setCount(int count) {this.count = count;}public List getList() {return list;}public void setList(List list) {this.list = list;}}
最后,我们在cn.itcast.b_dao包下创建一个类——UserDao.java。UserDao类里面编写代码实现对数据库完整的操作(CRUD)。
public class UserDao {/** 保存*/public void save(User user) {Session session = HibernateUtils.openSession();try {Transaction tx = session.beginTransaction(); // 开启事务session.save(user);tx.commit(); // 提交事务} catch (RuntimeException e) {session.getTransaction().rollback(); // 回滚事务throw e;} finally {session.close(); // 关闭session}}/** 更新*/public void update(User user) {Session session = HibernateUtils.openSession();Transaction tx = null;try {tx = session.beginTransaction();session.update(user);// 操作tx.commit();} catch (RuntimeException e) {tx.rollback();throw e;} finally {session.close();}}/** 删除*/public void delete(int id) {Session session = HibernateUtils.openSession();Transaction tx = null;try {tx = session.beginTransaction();Object user = session.get(User.class, id); // 要先获取到这个对象session.delete(user); // 删除的是实体对象tx.commit();} catch (RuntimeException e) {tx.rollback();throw e;} finally {session.close();}}/** 根据id查询一个User数据*/public User getById(int id) {Session session = HibernateUtils.openSession();Transaction tx = null;try {tx = session.beginTransaction();User user = (User) session.get(User.class, id);// 操作tx.commit();return user;} catch (RuntimeException e) {tx.rollback();throw e;} finally {session.close();}}/** 查询所有*/public List<User> findAll() {Session session = HibernateUtils.openSession();Transaction tx = null;try {tx = session.beginTransaction();// 方式一:使用HQL语句List<User> list = session.createQuery("FROM User").list(); // 使用HQL查询tx.commit();return list;} catch (RuntimeException e) {tx.rollback();throw e;} finally {session.close();}}/*** 分页的查询数据列表* @param firstResult 从结果列表中的哪个索引开始取数据* @param maxResults 最多取多少条数据* @return 一页的数据列表*/@SuppressWarnings("unchecked")public QueryResult findAll(int firstResult, int maxResults) {Session session = HibernateUtils.openSession();Transaction tx = null;try {tx = session.beginTransaction();// 查询一页的数据列表// 方式一:// Query query = session.createQuery("FROM User");// query.setFirstResult(firstResult);// query.setMaxResults(maxResults);// List<User> list = query.list(); // 使用HQL查询// 方式二:方法链List<User> list = session.createQuery( //"FROM User") //.setFirstResult(firstResult) // .setMaxResults(maxResults) //.list();// 查询总记录数// session.createQuery("SELECT COUNT(*) FROM User").list().get(0);// Long count = (Long) session.createQuery("SELECT COUNT(*) FROM User").uniqueResult();Long count = (Long) session.createQuery( //"SELECT COUNT(*) FROM User") //.uniqueResult();tx.commit();// 返回结果return new QueryResult(count.intValue(), list);} catch (RuntimeException e) {tx.rollback();throw e;} finally {session.close();}}}
在如下两个方法中:
public List<User> findAll()
public QueryResult findAll(int firstResult, int maxResults)
我们使用到了Hibernate查询语句——HQL(Hibernate Query Language),后面将会详细讲解,这里稍微了解一下即可,我们只要会用就好。
HQL(Hibernate Query Language)与SQL相似,查询的是对象和对象中的属性,关键字不区分大小写,但类名与属性名区分大小写;而SQL查询的是表和表中的字段,同样也不区分大小写。
接下来,为方便测试,我们使用单元测试来测试以上编写的代码。我们只要右键点击UserDao类→New→JUnit Test Case,如下:
接下来会弹出如下对话框:
这是要帮我们自动创建UserDao测试类的节奏。
接着点击Next按钮,在弹出的对话框中选中我们要测试的UserDao类中的方法。
最后点击Finish完成,这时Eclipse就帮我们自动创建UserDao类的测试类
——UserDaoTest.java了,然后我们再在其中编写测试代码。
public class UserDaoTest {private UserDao userDao = new UserDao();@Testpublic void testSave_1() {User user = new User();user.setName("张三");// 保存userDao.save(user);}@Testpublic void testGetById() {User user = userDao.getById(1);System.out.println(user);}@Testpublic void testUpdate() {// 从数据库中获取一条存在的数据User user = userDao.getById(1);user.setName("李四");// 更新userDao.update(user);}@Testpublic void testDelete() {userDao.delete(1);}// -------------------------@Testpublic void testSave_25() {for (int i = 1; i <= 25; i++) {User user = new User();user.setName("test_" + i);userDao.save(user); // 保存}}@Testpublic void testFindAll() {List<User> list = userDao.findAll();for (User user : list) {System.out.println(user);}}@Testpublic void testFindAllIntInt() {// 查询// QueryResult qr = userDao.findAll(0, 10); // 第1页,每页10条// QueryResult qr = userDao.findAll(10, 10); // 第2页,每页10条QueryResult qr = userDao.findAll(20, 10); // 第3页,每页10条// 显示结果System.out.println("总记录数:" + qr.getCount());for (User user : (List<User>) qr.getList()) {System.out.println(user);}}}
测试,全部通过,大发!
Hibernate框架基础——Hibernate入门相关推荐
- (转)Hibernate框架基础——一对多关联关系映射
http://blog.csdn.net/yerenyuan_pku/article/details/52746413 上一篇文章Hibernate框架基础--映射集合属性详细讲解的是值类型的集合(即 ...
- (转)Hibernate框架基础——Java对象持久化概述
http://blog.csdn.net/yerenyuan_pku/article/details/52732990 Java对象持久化概述 应用程序的分层体系结构 基于B/S的典型三层架构 说 ...
- (转)Hibernate框架基础——映射主键属性
http://blog.csdn.net/yerenyuan_pku/article/details/52740744 本文我们学习映射文件中的主键属性,废话不多说,直接开干. 我们首先在cn.it ...
- (转) Hibernate框架基础——操纵持久化对象的方法(Session中)
http://blog.csdn.net/yerenyuan_pku/article/details/52761021 上一篇文章中我们学习了Hibernate中java对象的状态以及对象的状态之间如 ...
- (转)Hibernate框架基础——在Hibernate中java对象的状态
http://blog.csdn.net/yerenyuan_pku/article/details/52760627 在Hibernate中java对象的状态 Hibernate把对象分为4种状态: ...
- (转)Hibernate框架基础——cascade属性
http://blog.csdn.net/yerenyuan_pku/article/details/52760010 我们以部门和员工的关系为例讲解一对多关联关系映射时,删除部门时,如果部门有关联的 ...
- (转)Hibernate框架基础——多对多关联关系映射
http://blog.csdn.net/yerenyuan_pku/article/details/52756536 多对多关联关系映射 多对多的实体关系模型也是很常见的,比如学生和课程的关系.一个 ...
- (转)Hibernate框架基础——映射集合属性
http://blog.csdn.net/yerenyuan_pku/article/details/52745486 集合映射 集合属性大致有两种: 单纯的集合属性,如像List.Set或数组等集合 ...
- (转)Hibernate框架基础——映射普通属性
http://blog.csdn.net/yerenyuan_pku/article/details/52739871 持久化对象与OID 对持久化对象的要求 提供一个无参的构造器.使Hibernat ...
最新文章
- 【转】ubuntu下实用的三款录屏软件
- 系统如何安装到租的服务器,租用服务器后,检查及环境配置步骤
- 华人“军火专家”——黄仁勋 1
- 使用.NET中的XML注释(一) -- XML注释标签讲解
- 傻孩子的故事--写给为编程而努力的HiccDS
- 在XenApp如何发布SAP的客户端(上)
- MODIS NDVI数据处理相关问题
- 编写脚本电脑怎么编写界面_在任何无法理解的情况下,请编写脚本
- SpringBoot找不到或无法加载主类
- 新建文件的UID和GID
- 前端开发的模块化和组件化的定义,以及两者的关系?
- 狭义相对论的一点点理解
- 数字化医院网络终端安全管理
- arcolinux使用i3wm窗口管理器
- 【编程算法】跳跃游戏ⅠⅡⅢ(Python解法)
- Mac OS 系统瘦身 - xcode 清理
- 一个C语言编写的贪吃蛇游戏
- Github 上的个人项目开源心得
- 2021-05-28 aps助油田服务与设备行业实现数字化
- linux中继器设置密码,无线扩展器管理员密码_初始密码是多少?-192路由网
热门文章
- 杭州福斯特光伏材料股份有限公司2016年年度股东大会决议公告
- 建筑外墙平台广告牌的室外用丙烯酸聚氨酯防腐面漆 漆膜颜色多样
- datagrid可编辑表格
- 2021届民航乘务高考成绩查询,2021年广州民航职业技术学院录取查询入口,高考录取结果查询网址登录...
- 增压器为Android应用程序雨燕,机械增压器进化史详解.doc
- 【shell实战】使用shell实现一个进度条
- C. Orac and LCM
- 利用金箔形成的暗能量制造出的虫洞穿越空间的机器
- jsp班主任辅导员管理系统
- 使用brainconn工具绘制的大脑连接数据,比BrainNet更方便和灵活