前言
在学习hibernate之前我们先回顾之前的数据库操作技术。之前是用原始的jdbc操作数据库,主要是通过Connection/Statement/ResultSet这三个类来对数据库进行操作的。还有一个DbUtils组件, 轻量级的组件其实也是封装了原生态的jdbc操作。这里就不在赘述之前的知识了。
ORM概念
O, Object 对象
R, Relation 关系 (关系型数据库: MySQL, Oracle…)
M,Mapping 映射
ORM, 解决什么问题?
简单来说就是:
存储: 能否把对象的数据直接保存到数据库?
获取: 能否直接从数据库拿到一个对象?
但是想做到上面2点,必须要有映射!—对象和数据库表的映射
什么是hibernate?
其实就是将对象进行持久化,保存起来。
持久化(Persistence),即把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘)。持久化的主要应用是将内存中的对象存储在关系型的数据库中,当然也可以存储在磁盘文件中、XML数据文件中等等。
Hibernate是ORM的实现,学习hibernate可以简化我们对数据库操作的代码,提高开发效率。其hibernate最重要的就是配置文件,也就是所谓的表域对象之间映射关系说明。
Hibernate 常用 Api
|– Configuration 配置管理类对象
config.configure(); 加载主配置文件的方法(hibernate.cfg.xml)
可以带路径参数,默认是加载路径“src/hibernate.cfg.xml”
config.configure(“cn/config/hibernate.cfg.xml”); 加载指定路径下指定名称的主配置文件
config.buildSessionFactory(); 创建session的工厂对象
|– SessionFactory session的工厂(或者说代表了这个hibernate.cfg.xml配置文件)
sf.openSession(); 创建一个sesison对象
sf.getCurrentSession(); 创建session或取出session对象
|–Session session对象维护了一个连接(Connection), 代表了与数据库连接的会话。
Hibernate最重要的对象: 只用使用hibernate与数据库操作,都用到这个对象
session.beginTransaction(); 开启一个事务; hibernate要求所有的与数据库的操作必须有事务的环境,否则报错!
更新:
session.save(obj); 保存一个对象
session.update(emp); 更新一个对象
session.saveOrUpdate(emp); 保存或者更新的方法:
没有设置主键,执行保存;
有设置主键,执行更新操作;
如果设置主键不存在报错!
主键查询:
session.get(Employee.class, 1); 主键查询
session.load(Employee.class, 1); 主键查询 (支持懒加载)
做了这么多准备工作,那我们开始今天的案例学习吧!
第一个crud案例
需求描述:实现员工信息的增删改查操作。
本次案例基本涵盖了hibernate操作数据库的方法。
搭建一个Hibernate环境,开发步骤:
1.下载源码
版本:hibernate-distribution-3.6.0.Final
2. 引入jar文件
hibernate3.jar核心 + required 必须引入的(6个) + jpa 目录 + 数据库驱动包
一共9个jar文件:
hibernate3.jar
antlr-2.7.6.jar
commons-collections-3.1.jar
dom4j-1.6.1.jar
javassist-3.12.0.GA.jar
jta-1.1.jar
slf4j-api-1.6.1.jar
hibernate-jpa-2.0-api-1.0.0.Final.jar
mysql-connector-java-5.1.12-bin.jar
3. 写对象以及对象的映射(重点 配置)
Employee.java 对象
Employee.hbm.xml 对象的映射 (映射文件)
4. src/hibernate.cfg.xml 主配置文件
- 数据库连接配置
- 加载所用的映射(*.hbm.xml)
5.编写代码
实体类Employee.java
//一、 对象
public class Employee {
private int empId;
private String empName;
private Date workDate;
public int getEmpId() {
return empId;
}
public void setEmpId(int empId) {
this.empId = empId;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public Date getWorkDate() {
return workDate;
}
public void setWorkDate(Date workDate) {
this.workDate = workDate;
}
@Override
public String toString() {
return "Employee [empId=" + empId + ", empName=" + empName
+ ", workDate=" + workDate + "]";
}
}
定义接口 IEmployeeDao .java
public interface IEmployeeDao {
void save(Employee emp);//保存
void update(Employee emp);//修改
Employee findById(Serializable id);//根据主键查询
List<Employee> getAll();//查询所有
List<Employee> getAll(String employeeName);//根据名称查询
List<Employee> getAll(int index, int count);//分页查询
void delete(Serializable id);//根据id删除
}
实现dao:EmployeeDaoImpl.java
public class EmployeeDaoImpl implements IEmployeeDao{
@Override
public Employee findById(Serializable id) {
Session session = null;
Transaction tx = null;
try {
// 获取Session
session = HibernateUtils.getSession();
// 开启事务
tx = session.beginTransaction();
// 主键查询
return (Employee) session.get(Employee.class, id);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
tx.commit();
session.close();
}
}
@Override
public List<Employee> getAll() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtils.getSession();
tx = session.beginTransaction();
// HQL查询
Query q = session.createQuery("from Employee");
return q.list();
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
tx.commit();
session.close();
}
}
@Override
public List<Employee> getAll(String employeeName) {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtils.getSession();
tx = session.beginTransaction();
Query q =session.createQuery("from Employee where empName=?");
// 注意:参数索引从0开始
q.setParameter(0, employeeName);
// 执行查询
return q.list();
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
tx.commit();
session.close();
}
}
@Override
public List<Employee> getAll(int index, int count) {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtils.getSession();
tx = session.beginTransaction();
Query q = session.createQuery("from Employee");
// 设置分页参数
q.setFirstResult(index); // 查询的其实行
q.setMaxResults(count); // 查询返回的行数
List<Employee> list = q.list();
return list;
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
tx.commit();
session.close();
}
}
@Override
public void save(Employee emp) {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtils.getSession();
tx = session.beginTransaction();
// 执行保存操作
session.save(emp);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
tx.commit();
session.close();
}
}
@Override
public void update(Employee emp) {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtils.getSession();
tx = session.beginTransaction();
session.update(emp);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
tx.commit();
session.close();
}
}
@Override
public void delete(Serializable id) {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtils.getSession();
tx = session.beginTransaction();
// 先根据id查询对象,再判断删除
Object obj = session.get(Employee.class, id);
if (obj != null) {
session.delete(obj);
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
tx.commit();
session.close();
}
}
}
注意:
使用hibernate框架自己数据库语言HQL语句。
HQL查询:
HQL查询与SQL查询区别:
SQL: (结构化查询语句)查询的是表以及字段; 不区分大小写。
HQL: hibernate query language 即hibernate提供的面向对象的查询语言
查询的是对象以及对象的属性。
区分大小写。
本次案例谢了一个hibernateUtils工具类,由于主配置文件只需要加载一次,故写在静态代码块中,然后写一个静态方法,用于返回session对象。
public class HibernateUtils {
private static SessionFactory sf;
static {
// 加载主配置文件, 并创建Session的工厂
sf = new Configuration().configure().buildSessionFactory();
}
// 创建Session对象
public static Session getSession(){
return sf.openSession();
}
}
对象关系映射文件-Employee.hbm.xml
<hibernate-mapping package="com.nwpu.geeker.helloworld">
<class name="Employee" table="employee">
<!-- 主键 ,映射-->
<id name="empId" column="id">
<generator class="native"/>
</id>
<!-- 非主键,映射 -->
<property name="empName" column="empName"></property>
<property name="workDate" column="workDate"></property>
</class>
</hibernate-mapping>
主配置文件:hibernate.cfg.xml
<hibernate-configuration>
<!-- 通常,一个session-factory节点代表一个数据库 -->
<session-factory>
<!-- 1. 数据库连接配置 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql:///hib_demo</property>
<property name="hibernate.connection.username">xxx</property>
<property name="hibernate.connection.password">xxx</property>
<!--
数据库方法配置, hibernate在运行的时候,会根据不同的方言生成符合当前数据库语法的sql
-->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
<!-- 2. 其他相关配置 -->
<!-- 2.1 显示hibernate在运行时候执行的sql语句 -->
<property name="hibernate.show_sql">true</property>
<!-- 2.2 格式化sql -->
<property name="hibernate.format_sql">true</property>
<!-- 2.3 自动建表 -->
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 3. 加载所有映射 -->
<mapping resource="com/nwpu/geeker/helloworld/Employee.hbm.xml"/>
</session-factory>
</hibernate-configuration>
测试:App.java
public class App {
private EmployeeDaoImpl empDao = new EmployeeDaoImpl();
@Test
public void testFindById() {
System.out.println(empDao.findById(1));
}
@Test
public void testGetAll() {
System.out.println(empDao.getAll());
}
@Test
public void testGetAllString() {
System.out.println(empDao.getAll("张三3"));
}
@Test
public void testGetAllIntInt() {
//分页查询
System.out.println(empDao.getAll(4, 2));
}
@Test
public void testSave() {
empDao.save(new Employee());
}
@Test
public void testUpdate() {
Employee emp = new Employee();
emp.setEmpId(23);
emp.setEmpName("new jack");
empDao.update(emp);
}
@Test
public void testDelete() {
empDao.delete(23);
}
}
本次案例也就接近尾声了,爱学习的小伙伴一起加油哦!