Hibernate01-简单的增删改查
Hibernate    2017-10-22 00:17:07    157    0    0
acme   Hibernate

Hibernate简介Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用,最具革命意义的是,Hibernate可以在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任。

 

1.Hibernate环境搭建

  1. 本次采用Maven做项目构建,使用Maven版本为3.5,jdk版本为9.0.1,Hibernate版本为5.0.1Final,数据库为MySQL5.7.20。
  2. 配置Maven的pom.xml文件,由于我当前的jdk版本以及Hibernate版本所以依赖如配置文件中所列出。
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
    <groupId>cc.acme_me.hibernate</groupId>
     <artifactId>Hibernate01</artifactId>
     <version>1.0-SNAPSHOT</version>
     <name>Hibernate01</name>
    <dependencies>
    <!-- junit -->
     <dependency>
     <groupId>junit</groupId>
     <artifactId>junit</artifactId>
     <version>4.12</version>
     <scope>test</scope>
     </dependency>
    <!-- mysql-connector-java -->
     <dependency>
     <groupId>mysql</groupId>
     <artifactId>mysql-connector-java</artifactId>
     <version>6.0.6</version>
     </dependency>
    <dependency>
     <groupId>org.hibernate</groupId>
     <artifactId>hibernate-core</artifactId>
     <version>5.2.12.Final</version>
     </dependency>
    <dependency>
     <groupId>antlr</groupId>
     <artifactId>antlr</artifactId>
     <version>2.7.7</version>
     </dependency>
    <dependency>
     <groupId>com.fasterxml</groupId>
     <artifactId>classmate</artifactId>
     <version>1.3.4</version>
     </dependency>
    <dependency>
     <groupId>dom4j</groupId>
     <artifactId>dom4j</artifactId>
     <version>1.6.1</version>
     </dependency>
    <dependency>
     <groupId>org.hibernate.common</groupId>
     <artifactId>hibernate-commons-annotations</artifactId>
     <version>5.0.1.Final</version>
     </dependency>
    <dependency>
     <groupId>org.jboss.logging</groupId>
     <artifactId>jboss-logging</artifactId>
     <version>3.3.0.Final</version>
     </dependency>
    <dependency>
     <groupId>org.hibernate.javax.persistence</groupId>
     <artifactId>hibernate-jpa-2.1-api</artifactId>
     <version>1.0.0.Final</version>
     </dependency>
    <dependency>
     <groupId>org.javassist</groupId>
     <artifactId>javassist</artifactId>
     <version>3.20.0-GA</version>
     </dependency>
    <dependency>
     <groupId>org.jboss</groupId>
     <artifactId>jandex</artifactId>
     <version>2.0.3.Final</version>
     </dependency>
    <dependency>
     <groupId>org.jboss.logging</groupId>
     <artifactId>jboss-logging</artifactId>
     <version>3.3.0.Final</version>
     </dependency>
    <dependency>
     <groupId>org.jboss.spec.javax.transaction</groupId>
     <artifactId>jboss-transaction-api_1.2_spec</artifactId>
     <version>1.0.1.Final</version>
     </dependency>
    <dependency>
     <groupId>com.sun.xml.bind</groupId>
     <artifactId>jaxb-core</artifactId>
     <version>2.3.0</version>
     </dependency>
     <dependency>
     <groupId>javax.xml.bind</groupId>
     <artifactId>jaxb-api</artifactId>
     <version>2.3.0</version>
     </dependency>
     <dependency>
     <groupId>com.sun.xml.bind</groupId>
     <artifactId>jaxb-impl</artifactId>
     <version>2.3.0</version>
     </dependency>
     <dependency>
     <groupId>javax.activation</groupId>
     <artifactId>activation</artifactId>
     <version>1.1.1</version>
     </dependency>
     </dependencies>
    </project>​
  3. 配置好Maven依赖以后,Hibernate需要自己的全局配置文件hibernate.cfg.xml
 <?xml version="1.0" encoding="UTF-8"?>
<!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>
 <!--数据库连接设置-->
 <property name="connection.username">root</property>
 <property name="connection.password">root</property>
 <property name="connection.url">jdbc:mysql://localhost:3306/db_hibernate</property>
 <property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property>
 <!--数据库方言-->
 <property name="dialect">org.hibernate.dialect.MySQL57Dialect</property>
 <!--显示sql语句-->
 <property name="show_sql">true</property>
 <!--格式化sql语句-->
 <property name="format_sql">true</property>
 <!--设置ddl 根据设置自动更新表结构 包括添加删除表 更新表结构-->
 <property name="hbm2ddl.auto">create-drop</property>
 <!-- 加载映射文件 -->
 <mapping resource="cc/acme_me/model/Student.hbm.xml"></mapping>
 </session-factory>
</hibernate-configuration>​ 

4.当配置好Maven写好了依赖的包,又配置好了Hibernate全局的基础配置文件以后,接下里就可以使用Hibernate用于开发了。

由于是第一章,我们便简单测试一下Hibernate的增删改查。首先我们建立一个实体类Student。

package cc.acme_me.model;
public class Student {
 private long id;//作为主键
 private String name;//姓名
 private int age;//年龄
public long getId() {
 return id;
 }
public void setId(long id) {
 this.id = id;
 }
public String getName() {
 return name;
 }
public void setName(String name) {
 this.name = name;
 }
public int getAge() {
 return age;
 }
public void setAge(int age) {
 this.age = age;
 }
}​

然后为这个实体类建立一个映射文件,映射文件以类名加上.hbm.xml。所以Student实体类的映射文件就是Student.hbm.xml了。虽然这个映射文件的名字是可以随意取的,只要在Hibernate全局配置文件中加载到就可以,但是不建议这样做。

<?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">
<hibernate-mapping package="cc.acme_me.model">
    <!--类所对应的表的-->
 <class name="Student" table="t_student">
     <!--用id设置主键 name对应的是实体类的字段 column对应表的列名 type是指字段的类型,可以使用Java的数据类型,也可以使用数据库的数据类型-->
 <id name="id" column="id" type="long">
     <!--这一行表示主键增长策略-->
 <generator class="increment"></generator>
 </id>
 <!--property配置普通的字段在表中对应的列-->
 <property name="name" column="name" type="string"></property>
 <property name="age" column="age" type="int"></property>
 </class>
</hibernate-mapping>​

当然,现在开发比较流行无配置或者叫做零配置开发,便是使用注解的方式。本章使用xml配置文件进行配置,在后面的博客中会慢慢转变使用注解的方式。

在这个映射文件中,是将实体类和数据库中的表进行对应。此时我们已经将这个映射文件在Hibernate全局文件中加载了,我们便可以对这个实体类进行操作了。

为了方便,我们可以建立一个工具类。

package cc.acme_me.utils;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.service.ServiceRegistry;
public class SessionUtils {
public static Session openSession() {
 ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().configure().build();
 SessionFactory sessionFactory = new MetadataSources(serviceRegistry).buildMetadata().buildSessionFactory();
 return sessionFactory.openSession();
 }
}​

这个工具类很简单,仅仅封装了一个简单的获取session的静态方法。该方法内的session获取方式是官方建议适用于5.0的方法(在Hibernate3.x和4.x官方也有另外建议的方法,感觉这个建议方法一个大版本就变一次啊)。

接着,我们写一个测试类

package cc.acme_me.test;
import cc.acme_me.model.Student;
import cc.acme_me.utils.SessionUtils;
import org.hibernate.Session;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class TestStudent {
 private Session session = null;
@Before//使用该注解可以在测试方法运行前调用,我们可以使用它将获取session的方法写好,就不需要为每一个测试方法写一遍session的获取
 public void openSession() {
 session = SessionUtils.openSession();
 session.beginTransaction();
 }
@After//该注解是在测试方法运行后调用,我们可以在这里设置事物的提交和session的关闭
 public void closeSession() {
 session.getTransaction().commit();
 session.close();
 }
}​

写好了测试之后,便开始在测试类里面添加测试方法。

既然是增删改查,那么我们便从添加开始。

@Test
public void testAdd() {
 //新建一个实体对象并设置参数
 Student student = new Student();
 student.setAge(18);
 student.setName("Admin");
 //由于我们在主键策略里面使用了自增长策略,所以可以不用配置ID,Hibernate可以为我们自动生成
 //使用save方法将实体对象持久化到数据库中
 session.save(student);
}​

添加方法写完,对着这个方法run一下,红条失败绿条通过。

在运行时,控制台或显示一条条的日志信息,在Hibernate的全局配置中,我们配置了格式化并显示SQL语句,所以当绿条通过后我们可以查看到Hibernate生成的SQL语句。

 drop table if exists t_student​

首先第一条我们看到了DDL语句,我们的配置参数是create-drop所以,Hibernate每次都会删除表以后新建。

create table t_student (
 id bigint not null,
 name varchar(255),
 age integer,
 primary key (id)
 ) engine=InnoDB​

 

select
 max(id) 
 from
 t_student
Hibernate: 
 insert 
 into
 t_student
 (name, age, id) 
 values
 (?, ?, ?)​

看完了Hibernate生成的sql语句,是不是感觉Hibernate的确是一个强大的东西呢?

查看t_student这张表的时候我们可以发现,数据的确插入进去了。

那么,接下来我们就写一个查找的测试吧,这样我们自己查询表里面的数据了。注意:在运行西面的测试方法之前,要将ddl从create-drop修改成update,否则在运行查找方法之前Hibernate现将表删除再新建,自然表里就不能查到数据了。

@Test
 public void testFind(){
 Student student = session.get(Student.class,1L);
 System.out.println(student);
 }​

为了方便显示,我们重写了Student的toString方法。使用session的get方法查询,传入要查询的类和主键的内容(如果想要问我为什么1后面有个L,那么我觉得你需要去再巩固一下Java基础了)。

select
 student0_.id as id1_0_0_,
 student0_.name as name2_0_0_,
 student0_.age as age3_0_0_ 
from
 t_student student0_ 
where
 student0_.id=?​

上面便是Hibernate自动生成的查询语句,下面显示的是控制台打印出来的student。

Student{id=1, name='Admin', age=18}

接下来便是修改和删除,那么我们继续。

@Test
 public void testUpdate(){
 Student student = session.get(Student.class,1L);
 student.setName("Administrator");
 student.setAge(20);
 session.update(student);// session.saveOrUpdate(student); 可以使用这两个方法更新数据,后者相比前者,可以在你不确定是更新还是添加数据的时候交由Hibernate去判断并调用合适的方法
 }​

调用方法就可以看到Hibernate生成的语句

select
 student0_.id as id1_0_0_,
 student0_.name as name2_0_0_,
 student0_.age as age3_0_0_ 
from
 t_student student0_ 
where
 student0_.id=?
Hibernate: 
update
 t_student 
set
 name=?,
 age=? 
where
 id=?​

接着我们使用上面的查询方法再次查询这条数据,会发现数据真的出现了变化。

Student{id=1, name='Administrator', age=20}

接着便是这一章简单增删改查的最后一条,数据删除。测试方法如下:

@Test
 public void testDelete(){
 Student student = new Student();
 student.setId(1L);
 session.delete(student);
 //session.delete(session.get(Student.class,1L));
 }​

在删除测试方法中,最后一行被我注释掉的方法等效于前面三行的操作。

对表中的数据是基于主键操作的,所以我们只要保证主键这个值(Student我们设置的主键是id)存在,那么便可以通过主键查询到数据进行操作。

delete 
 from
 t_student 
 where
 id=?​

上面便是自动生成的sql语句,我们再使用查询方法查询。

控制台显示为null,说明并没有查询到我们需要的数据。

从数据库中发现已经没有数据了,便说明已经成功删除了这一条数据。

Pre: Hibernate02-简单的注解操作

Next: HTTPRequestHead

157
Table of content