Hibernate框架
用于实现关系型数据库访问操作。例如Oracle、Mysql。
是基于ORM思想将jdbc进行了封装,实现对象关系映射。
目标:将关系表中数据映射成Java中实体对象,程序员对对象操作从而实现对数据库操作
Hibernate和MyBatis的区别
1.Hibernate复杂度比MyBatis高,功能多
2.Hibernate自动生成SQL,MyBatis编写SQL
3.Hibernate关联映射种类多,Mybatis简单就@one和@Many
4.Hibernate提供了多种操作方式,HQL、Criteria、NativeSQL三种操作
5.Hibernate还封装了缓存、延迟加载、持久化等特性
6.Hibernate直接实现对象到数据库映射,Mybatis实现对象到SQL参数映射
Hibernate操作
1.导入Hibernate开发包、数据库驱动包、junit测试包
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.3.1.Final</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
2.追加主配置文件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">
<!-- Generated by MyEclipse Hibernate Tools. -->
<hibernate-configuration>
<session-factory>
<property name="dialect">
org.hibernate.dialect.MySQLDialect <!-- Mysql数据库的翻译,Oracle的就用Oracle的。。。 -->
</property>
<property name="connection.url">
jdbc:mysql://localhost:3306/test
</property>
<property name="connection.username">root</property>
<property name="connection.password">123456</property>
<property name="connection.driver_class">
com.mysql.jdbc.Driver
</property>
<!-- 加载映射描述信息 -->
<mapping resource="hbm/Subject.hbm.xml" />
</session-factory>
</hibernate-configuration>
3.根据操作表编写Java实体类
public class Subject implements Serializable{
private Integer id;
private String name;
private Integer directionId;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getDirectionId() {
return directionId;
}
public void setDirectionId(Integer directionId) {
this.directionId = directionId;
}
}
4.根据表和类,编写映射信息(XML或注解)此处使用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">
<hibernate-mapping>
<class name="cn.xdl.entity.Subject" table="SUBJECT">
<id name="id" column="ID"></id> <!--主键 -->
<property name="name" column="NAME"></property>
<property name="directionId" column="DIRECTION_ID"></property>
</class>
</hibernate-mapping>
5.获取Session数据库操作对象进行操作
5.1封装Util获取Session
package cn.xdl.util;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtil {
public static Session getSession() {
//加载主配置文件hibernate.cfg.xml
Configuration conf = new Configuration();
conf.configure("hibernate.cfg.xml");
//获取SessionFactory
SessionFactory factory = conf.buildSessionFactory();
//获取session
Session session = factory.openSession();
return session;
}
}
5.2创建测试类进行增删查改的操作。
package ssh03;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import cn.xdl.entity.Subject;
import cn.xdl.util.HibernateUtil;
public class TestSubject {
//xml文件映射基础方法使用
//添加
@Test
public void test1(){
Subject subject = new Subject();
subject.setId(50);
subject.setName("JAVA");
subject.setDirectionId(2);
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
session.save(subject);
tx.commit();
session.close();
}
//修改
@Test
public void test2(){
Subject subject = new Subject();
subject.setId(50);
subject.setName("PYTHON");
subject.setDirectionId(2);
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
session.update(subject);
tx.commit();
session.close();
}
//根据id删除
@Test
public void test3(){
Subject subject = new Subject();
subject.setId(50);
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
session.remove(subject);
tx.commit();
session.close();
}
//根据id查询
@Test
public void test4(){
Session session = HibernateUtil.getSession();
Subject subject = (Subject)session.get(Subject.class, 50);
System.out.println(subject.getId()+" "+subject.getName());
session.close();
}
}
Hibernate主键生成
Hibernate框架集成了主键ID生成方法,在添加时有效。
可以在映射描述配置文件Subject.hbm.xml中指定以下类型。
-
identity
适用于MySQL、SQLServer等带自动递增类型的数据库。在添加时,采用数据库自动递增生成ID值。
<id name="id" column="ID"> <generator class="identity"></generator> </id>
-
sequence
适用于Oracle、DB带序列的数据库。在添加时,采用指定序列生成ID值。
-
increment
适用于多种数据库。在添加时,先查询ID最大值,然后加1后进行插入。
-
native
根据dialect方言设置判断,如果是Oracle就采用sequence,如果是MySQL就采用identity
-
uuid
添加时生成一个UUID字符串值做主键。
-
assigned
默认值,意思是Hibernate忽略不管理ID主键,需要程序员在代码中设置ID值,否则不正常。
为了方便程序员查看框架自行处理的sql语句可以在hibernate.cfg.xml主配置文件中开启sql语句的输出和格式化。有助于了解内部执行过程可以用于后期优化。
<!-- 后台显示框架处理的sql语句并格式化 -->
<property name="show_sql">true</property>
<property name="format_sql">true</property>
注解映射描述(是JPA的典型)
写一个实体类,在实体类中使用注解进行映射描述
@Entity
@Table(name="SUBJECT")
public class Subject2 implements Serializable{
@Id
@GeneratedValue(strategy=GenerationType.AUTO)//主键
@Column(name="ID")
private Integer id;
@Column(name="NAME")
private String name;
@Column(name="DIRECTION_ID")
private Integer directionId;
。。。省略getset方法自行生成
}
在hibernate.cfg.xml主配置文件中加载映射描述
<mapping class="cn.xdl.entity.Subject2"/>
测试类:
//注解映射用法 查询,此处只举例说明了查询方法其他方法和配置xml文件相同
@Test
public void test1(){
Session session = HibernateUtil.getSession();
//load和get的区别在于查询时是否延迟,load延迟查询
Subject2 load = session.load(Subject2.class, 50);
System.out.println(load.getId()+" "+load.getName());
session.close();
}
结果:
Hibernate操作
Hibernate提供了HQL、Criteria、NativeSQL三种操作方式。
-
HQL语句
Hibernate Query Language,属于面向对象查询语言。
HQL语法结构与SQL相似,支持select...from...where...group by...having...order by...,区别如下:
SQL: select ID,NAME from DIRECTION
HQL: select id,name from Direction
HQL: from Direction
HQL: from Direction where name like ?
HQL: select count(*) from Direction
- HQL使用类名、属性名;SQL使用表名、字段名
- HQL大小写敏感,类名和属性名与实际保持一致
- HQL语句不支持select *写法,可以省略
- HQL语句不支持join...on结构的on子句
- HQL语句不支持数据库特有函数和关键词
通过Subject2实体类的注解映射描述进行HQL语句的操作。
//查询所有
@Test
public void test2(){
Session session = HibernateUtil.getSession();
Query<Subject2> query = session.createQuery("from Subject2");
List<Subject2> list = query.getResultList();
for (Subject2 subject2 : list) {
System.out.println(subject2.getId()+" "+subject2.getName());
}
session.close();
}
//jpa语法格式查询name做条件带参数的
@Test
public void test3(){
Session session = HibernateUtil.getSession();
Query<Subject2> query = session.createQuery("from Subject2 where name like ?1");
query.setParameter(1, "%JAVA%");
List<Subject2> list = query.getResultList();
for (Subject2 subject2 : list) {
System.out.println(subject2.getId()+" "+subject2.getName());
}
session.close();
}
// Hibernate语法格式查询name做条件带参数的
@Test
public void test4() {
Session session = HibernateUtil.getSession();
Query<Subject2> query = session.createQuery("from Subject2 where name like :name");
query.setParameter("name", "%JAVA%");
List<Subject2> list = query.getResultList();
for (Subject2 subject2 : list) {
System.out.println(subject2.getId() + " " + subject2.getName());
}
session.close();
}
// 单行等值查询,单行可以使用uniqueResult()
@Test
public void test5() {
Session session = HibernateUtil.getSession();
Query<Subject2> query = session.createQuery("from Subject2 where id = :id");
query.setParameter("id",50);
Subject2 subject2 = query.uniqueResult();
System.out.println(subject2.getId()+" "+subject2.getName());
session.close();
}
//查询总记录数或者具体某一个值只需要在select后指定就行
@Test
public void test6() {
Session session = HibernateUtil.getSession();
Query<Long> query = session.createQuery("select count(*) from Subject2");
Long size = query.uniqueResult();
System.out.println("总记录数:"+size);
session.close();
}
// 查询所有信息,分页语句具体实现和方言有关
//<property name="dialect">
//org.hibernate.dialect.MySQLDialect <!-- Mysql数据库的翻译,Oracle的就用Oracle的。。。 -->
//</property>
@Test
public void test7() {
Session session = HibernateUtil.getSession();
Query<Subject2> query = session.createQuery("from Subject2");
//设置分页
query.setFirstResult(0);//设置抓取记录起点,从0开始
query.setMaxResults(3);//设置抓取最大记录数量
List<Subject2> list = query.getResultList();
for (Subject2 subject2 : list) {
System.out.println(subject2.getId() + " " + subject2.getName());
}
session.close();
}
Native SQL
可以将原始SQL语句发送给数据库执行。
package ssh03;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.query.NativeQuery;
import org.junit.Test;
import cn.xdl.entity.Subject2;
import cn.xdl.util.HibernateUtil;
public class TestSQL {
//查询所有
@Test
public void test1(){
String sql = "select * from subject"; //表名
Session session = HibernateUtil.getSession();
NativeQuery nativeQuery = session.createNativeQuery(sql);
List<Object[]> resultList = nativeQuery.getResultList();//默认使用Object[] 数组类型
for (Object[] object : resultList) {
System.out.println(object[0]+" "+object[1]);
}
session.close();
}
@Test
public void test2(){
String sql = "select * from subject";
Session session = HibernateUtil.getSession();
NativeQuery nativeQuery = session.createNativeQuery(sql);
nativeQuery.addEntity(Subject2.class);//指定使用Subject2封装一条记录
List<Subject2> resultList = nativeQuery.getResultList();
for (Subject2 object : resultList) {
System.out.println(object.getId()+" "+object.getName());
}
session.close();
}
//查询name做条件带参数的
@Test
public void test3(){
String sql = "select * from subject where name like ?";
Session session = HibernateUtil.getSession();
NativeQuery nativeQuery = session.createNativeQuery(sql);
nativeQuery.setParameter(1, "%JAVA%");
nativeQuery.addEntity(Subject2.class);//指定使用Subject2封装一条记录
List<Subject2> resultList = nativeQuery.getResultList();
for (Subject2 object : resultList) {
System.out.println(object.getId()+" "+object.getName());
}
session.close();
}
//分页查询
@Test
public void test4(){
String sql = "select * from subject";
Session session = HibernateUtil.getSession();
NativeQuery nativeQuery = session.createNativeQuery(sql);
nativeQuery.addEntity(Subject2.class);//指定使用Subject2封装一条记录
//设置分页参数
nativeQuery.setFirstResult(0);
nativeQuery.setMaxResults(3);
List<Subject2> resultList = nativeQuery.getResultList();
for (Subject2 object : resultList) {
System.out.println(object.getId()+" "+object.getName());
}
session.close();
}
}
实现底层语句和结果:
Hibernate操作(Criteria)
查询操作,只是版本新旧问题,实现的查询效果相同。
@Test //5之前版本应用
public void test1(){
Session session = HibernateUtil.getSession();
Criteria criteria = session.createCriteria(Subject2.class);
criteria.add(Restrictions.like("name", "JAVA"));//类视sql语句的where
criteria.addOrder(Order.asc("id"));//排序
List<Subject2> list = criteria.list();
for (Subject2 subject2 : list) {
System.out.println(subject2.getId()+" "+subject2.getName());
}
session.close();
}
@Test //5版本之后应用
public void test2(){
Session session = HibernateUtil.getSession();
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<Subject2> criteriaQuery = builder.createQuery(Subject2.class);
//设置from、where、order
Root<Subject2> root = criteriaQuery.from(Subject2.class);
criteriaQuery.where(builder.like(root.get("name"), "%JAVA%"));
criteriaQuery.orderBy(builder.asc(root.get("id")));
//执行CriteriaQuery
Query<Subject2> query = session.createQuery(criteriaQuery);
List<Subject2> list = query.getResultList();
for (Subject2 subject2 : list) {
System.out.println(subject2.getId() + " " + subject2.getName());
}
session.close();
}
删除操作
@Test//5版本之后应用
public void test3(){
Session session = HibernateUtil.getSession();
//增删改必须开启事务
Transaction tx = session.beginTransaction();
CriteriaBuilder builder = session.getCriteriaBuilder();
//创建删除的criteria
CriteriaDelete<Subject> criteriaDelete =
builder.createCriteriaDelete(Subject.class);
//设置删除哪些记录
Root<Subject> root = criteriaDelete.from(Subject.class);
criteriaDelete.where(builder.like(root.get("name"), "hibernate%"));
//执行操作
Query<Subject> query = session.createQuery(criteriaDelete);
int size = query.executeUpdate();
System.out.println("删除的记录条数:"+size);
tx.commit();//提交事务
session.close();
}