【Java EE 学习 44】【Hibernate学习第一天】【Hibernate对单表的CRUD操作】

时间:2023-01-29 07:11:53

一、Hibernate简介

  1.hibernate是对jdbc的二次开发

  2.jdbc没有缓存机制,但是hibernate有。

  3.hibernate的有点和缺点

    (1)优点:有缓存,而且是二级缓存;完全的面向对象编程,代码操作比较简单。

    (2)缺点:大量的数据条件下不适合使用hibernate;程序员对hibernate生成的sql语句不可控,如果对sql优化的条件比较高,这时候也不适合使用hibernate。

  4.hibernate中称数据库中的表为持久化表,相对应的,建立的类称之为持久化类。

  5.hibernate中使用映射文件建立起持久化表和持久化类之间的映射关系。

  6.映射文件中需要建立的三种映射关系:表到类的映射;表的字段到类的属性之间的映射;字段类型到属性类型之间的映射。

  7.hibernate的配置信息:连接数据库的配置信息。

  8.hibernate的三大要素:配置文件、映射文件、持久化类。

  9.hibernate中将要学习的东西概括有:对单表进行增删查改;持久化类的状态;一对多和多对多的关系怎么转化为对对象的操作;优化;hql;数据缓存。

二、配置文件的配置

  配置mysql的模板:

<?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>
<!-- Database connection settings -->
<property name="connection.driver_class">
com.mysql.jdbc.Driver
</property>
<property name="connection.url">
jdbc:mysql://localhost:3306/test
</property>
<property name="connection.username">root</property>
<property name="connection.password">5a6f38</property>
<!-- 该配置语句的作用就是如果表存在就使用,如果表不存在则创建新的表 -->
<property name="hbm2ddl.auto">update</property>
<!-- 必须配置,如果在Junit下调试的话必须加上这段配置,否则报错 -->
<property name="javax.persistence.validation.mode">none</property>
<!-- 配置数据库方言,必须配置,否则报错找不到Dialect类 -->
<property name="dialect">
org.hibernate.dialect.MySQLDialect
</property>
<property name="show_sql">true</property>
<!-- 最后注册映射文件 -->
<mapping resource="com/kdyzm/hibernate/p01/firstapp/Person.hbm.xml" />
<mapping resource="com/mysql/hibernate/domain/Student.hbm.xml" />
<mapping resource="com/mysql/hibernate/domain/Classes.hbm.xml" />
</session-factory>
</hibernate-configuration>

  注意一定要在头部声明标准的约束,如dtd文件或者schema文件约束。

  1.需要注意的事项:除了连接数据库的地址、连接数据库的驱动、用户名、密码四个必须配置的因素之外,还必须配置的选项:

    (1)配置数据库方言:

<property name="dialect">
org.hibernate.dialect.MySQLDialect
</property>

      这里是配置mysql数据库的方言。

      如果这里需要配置其他数据库的方言,则需要查看相关手册。其他数据库包括oracle数据库、SQLServer数据库。

         org.hibernate.dialect.MySQL5Dialect       mysql数据库

  org.hibernate.dialect.Oracle9Dialect        oracle数据库

  org.hibernate.dialect.SQLServerDialect    SQLServer数据库

    (2)配置数据库的验证方式:

 <property name="hbm2ddl.auto">update</property>

    这个意思就是在加载配置文件的时候需要检查数据库中跟是否存在这个表,如果没有存在这个表,则根据配置文件中的配置自动创建这个表。

    四种验证方式分别是:  

       validate:加载hibernate时验证创建表结构

   update:加载hibernate时自动更新数据库结构,如果表存在不用创建,如果不存在就创建,这是最常使用的选项。

  create:每一次加载hibernate时都创建表结构

    create-drop:加载hibernate时创建,退出时删除

    (3)其它的可选项:

<property name="show_sql">true</property>

      该句配置的意思就是在hibernate在向数据库发出查询请求的时候发出的SQL语句必须显示出来。

<property name="javax.persistence.validation.mode">none</property>

      如果使用Juit进行单元测试,必须加上这句话,否则会报异常!

三、映射文件的配置。

  1.单表映射文件的模板

<?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>
<class name="com.mysql.hibernate.domain.Person" table="People" catalog="test">
<id name="id" type="java.lang.Long" length="5">
<column name="id"></column>
<generator class="increment"></generator>
</id>
<property name="name" type="java.lang.String" length="32">
<column name="name"></column>
</property>
<property name="age" type="java.lang.Integer" length="5">
<column name="age"></column>
</property>
<property name="sex" type="java.lang.String" length="4">
<column name="sex"></column>
</property>
</class>
</hibernate-mapping>

  其中需要注意的地方就是不要忘记了加上标准约束,如dtd约束或者schema约束。

  以上模板不涉及一对多关系、多对一关系、多对多关系,是最简单的映射文件的配置模板。

四、小例子:使用hibernate实现对单表的增删查改操作。

  使用的类:Person类,在数据库中对应的持久化表:People表,使用的数据库:test数据库

  1.配置文件放在classpath根目录下,如果该文件放在classpath根目录下,则hibernate会自动加载该配置文件。

 <?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>
<!-- Database connection settings -->
<property name="connection.driver_class">
com.mysql.jdbc.Driver
</property>
<property name="connection.url">
jdbc:mysql://localhost:3306/test
</property>
<property name="connection.username">root</property>
<property name="connection.password">5a6f38</property>
<!-- 该配置语句的作用就是如果表存在就使用,如果表不存在则创建新的表 -->
<property name="hbm2ddl.auto">update</property>
<!-- 必须配置,如果在Junit下调试的话必须加上这段配置,否则报错 -->
<property name="javax.persistence.validation.mode">none</property>
<!-- 配置数据库方言,必须配置,否则报错找不到Dialect类 -->
<property name="dialect">
org.hibernate.dialect.MySQLDialect
</property>
<property name="show_sql">true</property>
<!-- 最后注册映射文件 -->
<mapping resource="com/kdyzm/hibernate/p01/firstapp/Person.hbm.xml" />
</session-factory>
</hibernate-configuration>

hibernate.cfg.xml

  2.持久化类对应的映射文件,放置位置任意,但是需要放置在classpath目录下。

 <?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>
<class name="com.mysql.hibernate.domain.Person" table="People" catalog="test">
<id name="id" type="java.lang.Long" length="5">
<column name="id"></column>
<generator class="increment"></generator>
</id>
<property name="name" type="java.lang.String" length="32">
<column name="name"></column>
</property>
<property name="age" type="java.lang.Integer" length="5">
<column name="age"></column>
</property>
<property name="sex" type="java.lang.String" length="4">
<column name="sex"></column>
</property>
</class>
</hibernate-mapping>

Person.hbm.xml

  3.持久化类Person

 package com.mysql.hibernate.domain;

 import java.io.Serializable;

 public class Person implements Serializable{
private static final long serialVersionUID = 6596327961453463908L;
private Long id;
private String name;
private Integer age;
private String sex; public Person() {
}
public Person(Long id, String name, Integer age, String sex) {
this.id = id;
this.name = name;
this.age = age;
this.sex = sex;
}
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 Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "People [id=" + id + ", name=" + name + ", age=" + age
+ ", sex=" + sex + "]";
}
}

Person.java

  4.CRUD操作。

 package com.kdyzm.hibernate.p01.firstapp;

 import java.util.List;

 import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.Test; import com.mysql.hibernate.domain.Person; public class TestAdd {
private static SessionFactory sessionFatory;
static{
//建立配置文件
Configuration configuration=new Configuration();
//加载配置文件
configuration.configure();
//采用工厂模式创建sessionFactory对象
sessionFatory=configuration.buildSessionFactory();
}
//使用Hibernate的保存测试
@Test
public void testAddByHibernate(){
try {
Session session=sessionFatory.openSession();
Transaction transaction=session.beginTransaction();
Person p=new Person();
/*p.setId(11L);*/
p.setAge(12);
p.setName("张三");
p.setSex("男");
session.save(p);
transaction.commit();
session.close();
} catch (Exception e) {
e.printStackTrace();
}
}
//测试使用Hibernate的更新操作。
@Test
public void testUpdate(){
Session session=sessionFatory.openSession();
Transaction transaction = session.beginTransaction();
Person p=(Person) session.get(Person.class, 1L);
p.setName("测试修改Hibernate名称!");
session.update(p);
transaction.commit();
session.close();
}
//测试使用Hibernate的删除操作
@Test
public void testDelete(){
Session session=sessionFatory.openSession();
Transaction transaction=session.beginTransaction();
Person p=(Person) session.get(Person.class, 1L);
session.delete(p);
transaction.commit();
session.close();
}
//测试使用Hibernate的查询操作
@Test
public void testQuery(){
try {
Session session=sessionFatory.openSession();
//from后面跟上的是类名而不是表名,因为hibernate是从对象中获取数据的。
List<Person>list=session.createQuery("from Person").list();
System.out.println(list.size());
for(Person p:list)
{
System.out.println(p);
}
} catch (HibernateException e) {
e.printStackTrace();
}
}
}

SingleTableCRUD.java

五、主键生成策略。

表示符生成器

描述

Increment

由hibernate自动以递增的方式生成表识符,每次增量为1

Identity

由底层数据库生成表识符。条件是数据库支持自动增长数据类型。

Sequence

Hibernate根据底层数据库序列生成标识符。条件是数据库支持序列。

Native

根据底层数据库对自动生成表示符的能力来选择identity、sequence、hilo

Uuid.hex

Hibernate采用128位的UUID算法来生成标识符。该算法

能够在网络环境中生成唯一的字符串标识符,这种策略并不流行,因为字符串类型的主键比整数类型的主键占用更多的数据库空间。

如果主键用字符类型,并且不代表任何含义。

assigned

适用于自然主键。由java程序负责生成标识符。不能把setID()方法声明为

Private的。尽量避免使用自然主键。

六、hibernate类型和java标准类型。

  hibernate为了简化书写,对java标准类型和自定义类型进行了映射,这样在书写映射文件的时候就大大提高了书写效率,还能防止出错。具体映射关系见文档。

  比如,java.lang.String=string,java.lang.Long=long等

七、可以通过通过反向工程根据数据库中的表自动创建对应的持久化类和DAO等相关文件,但是使用该功能有前提,那就是添加hibernate到新建的工程。

  添加方法:

  【Java EE 学习 44】【Hibernate学习第一天】【Hibernate对单表的CRUD操作】