hibernate系列(一)hibernate入门

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
云数据库 RDS MySQL Serverless,价值2615元额度,1个月
简介:
最近开始学习hibernate,然后就想把这个学习历程总结下来。还是打算主要分两个过程,第一个过程:学会使用hibernate,第二个过程:做一些源码分析,更加深入的理解。 

言归正传,开始入门案例,这里的入门案例不牵扯其他框架,所以一开始学习的时候尽量不要牵扯其他框架,如SpringMVC。如果入门时牵涉其他框架,有时候会搞不清楚hibernate和其他框架的责任机制,本工程虽然搭建的是SpringMVC项目,主要是为后来服务,但是目前几乎用不到: 
hibernate有两种配置文件,一种就是像jdbc那样连接数据库的配置文件,另一种就是domain类和数据库表之间的映射文件。 

第一种配置文件,又有两种形式,可以是properties文件,也可以是xml文件,先来说下xml形式的文件,文件名为hibernate.cfg.xml,可以是其他文件名,如下:
 
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version= "1.0" encoding= "UTF-8" ?>
<!DOCTYPE hibernate-configuration PUBLIC
         "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
<hibernate-configuration>
     <session-factory name= "hibernateSessionFactory" >
         <property name= "hibernate.connection.driver_class" >com.mysql.jdbc.Driver</property>
         <property name= "hibernate.connection.password" >ligang</property>
         <property name= "hibernate.connection.url" >jdbc:mysql: //localhost:3306</property>
         <property name= "hibernate.connection.username" >root</property>
         <property name= "hibernate.dialect" >org.hibernate.dialect.MySQLDialect</property>
         <property name= "hibernate.show_sql" > true </property>
         <property name= "hibernate.default_schema" >hibernate</property>
     </session-factory>
</hibernate-configuration>

前面四个属性和jdbc配置是一样的,后面的hibernate.dialect即选择使用哪种方言,hibernate中有些特性是需要特定的数据库支持的,因此需要明确指定使用哪种方言,不同的数据库甚至相同的数据库不同的版本、不同的引擎,他们都有各自的方言实现,如mysql就有5种形式的方言。目前我还不是特别清楚,所以就暂时使用org.hibernate.dialect.MySQLDialect类,所有的方言都继承了Dialect类,如下所示:  

07102417_U9uu.png  
hibernate.show_sql属性为true则是将产生的sql语句显示出来。 
properties形式的,文件名是hibernate.properties文件,目前我还没找到是否允许是其他文件名。如下:
 
?
1
2
3
4
5
6
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.connection.driver_class=com.mysql.jdbc.Driver
hibernate.connection.url=jdbc:mysql: //localhost:3306/hibernate?useUnicode=true&characterEncoding=utf-8
hibernate.connection.username=root
hibernate.connection.password=ligang
hibernate.show_sql= true

和上面的xml文件没有什么区别。 

第二种配置文件,即domain类和数据库表的映射文件,先说domain类,如Customer类,如下:
 
?
1
2
3
4
5
6
7
8
public class Customer {
 
     private Long id;
     private String name;
     private String email;
     private Timestamp registeredTime;
         //省略get、set方法
}

对应的映射文件是:Customer.hbm.xml,可以是其他文件名,  
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version= "1.0" encoding= "UTF-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC
           "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
<hibernate-mapping>
     < class name= "com.ligang.domain.Customer" table= "customer" >
         <id name= "id" column= "id" type= "long" >
             <generator class = "identity" />
         </id>
         <property name= "name" column= "name" type= "string" />
         <property name= "email" column= "email" type= "string" />
         <property name= "registeredTime" column= "registeredTime" type= "timestamp" />
     </ class >
</hibernate-mapping>

其中class标签的name指明了哪个domain类,table指明该domain类所对应的数据库的表。 
id标签中的generator 来专门说明主键的生成策略,如可以是increment、identity、sequence、native等。 
increment:则是由hibernate自增来生成主键。 
identity:则是由底层数据库自增来生成主键,支持的数据库有:DB2、mysql、SqlServer等。 
sequence:也是有底层数据库来生成主键,支持的数据库有:DB2、oracle等。 
native:根据底层数据库所支持的能力,自动从identity、sequence中挑选一个作为主键的生成策略。 

然后就是property标签:name指明Customer的属性,column指明表的列名,type则是java类型和表中字段类型的桥梁。如java中的String类型,如果要映射到数据库中的varchar类型,则需要type为string,如果要映射到数据库中的text类型,则type为text。具体的类型间的映射关系可以到网上搜一搜。 

准备工作做完了,然后就要开始使用hibernate了,我的maven工程使用的是4.3.6.Final版本的hibernate,后面提供下载。 
hibernate的几个重要概念Configuration、SessionFactory、Session、Transaction、Query和Criteria: 
Configuration:用于配置和启动hibernate,然后可以创建出SessionFactory。 
SessionFactory:作为产生session的工厂,一个SessionFactory实例代表一个数据库存储源,如果要访问多个数据库,则需要为每个数据库创建一个单独的SessionFactory实例。它是重量级的,内部有很多缓存,不可随意创建和销毁。 
Session:用于增删改对象。 
Transaction:用于事务的功能。 
Query和Criteria:用于查询数据。 

首先,我声明了这样的一个接口HibernateDao,用于获取Session,如下:
 
?
1
2
3
4
public interface HibernateDao {
 
     public Session getSession();
}

它的实现类HibernateDaoImpl如下:  
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Repository
public class HibernateDaoImpl implements HibernateDao{
     
     private SessionFactory sessionFactory;
 
     public HibernateDaoImpl(){
         Configuration config= new Configuration();
         config.addClass(Customer. class );
         sessionFactory=config.buildSessionFactory();
     }
 
     @Override
     public Session getSession() {
         return sessionFactory.openSession();
     }
}

这里主要是对hibernate指明之前已说明的两种配置文件,一种连接数据库的配置文件,一种domain类对应数据库中表的配置文件。 
对于连接数据库的配置文件:如何接收properties形式的配置文件,又如何接收xml形式的配置文件。 
(1)接收properties形式的配置文件:对于上述的代码,config.buildSessionFactory()(这是一个过时的方法)会去尝试在类路径的根目录下加载hibernate.properties配置文件。我目前只知道这种形式来接收properties形式的配置文件,路径和文件名都是限制死的,证据如下:
 
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public SessionFactory buildSessionFactory() throws HibernateException {
         Environment.verifyProperties( properties );
         ConfigurationHelper.resolvePlaceHolders( properties );
         final ServiceRegistry serviceRegistry =  new StandardServiceRegistryBuilder()
                 .applySettings( properties )
                 .build();
         setSessionFactoryObserver(
                 new SessionFactoryObserver() {
                     @Override
                     public void sessionFactoryCreated(SessionFactory factory) {
                     }
 
                     @Override
                     public void sessionFactoryClosed(SessionFactory factory) {
                         ( (StandardServiceRegistryImpl) serviceRegistry ).destroy();
                     }
                 }
         );
         return buildSessionFactory( serviceRegistry );
     }

这里用到了Environment类,所以类加载器要去加载Environment类,并会执行它的静态代码块,如下:  

07102417_q7xt.png  

(2)接收xml形式的配置文件:需要使用config.configure(),如下所示:  
?
1
2
3
4
5
6
public HibernateDaoImpl(){
         Configuration config= new Configuration();
         config.configure();
         config.addClass(Customer. class );
         sessionFactory=config.buildSessionFactory();
     }

config.configure()会默认从类路径的根目录下去加载hibernate.cfg.xml配置文件,源代码如下:  
?
1
2
3
4
public Configuration configure() throws HibernateException {
         configure( "/hibernate.cfg.xml" );
         return this ;
}

config.configure()会调用含有参数的configure()方法,所以如果我们想在类路径下的子目录中去放置我们的配置文件,则需要使用含参数的configure(相对类路径的路径)。并且文件名可以随意指定,如我们的配置文件可以放到类路径下/hibernate/config/文件夹中,我可以这样配置config.configure("/hibernate/config/hibernate.cfg.xml")。 

对于domain类和数据库表之间的映射文件的加载,可以使用config.addClass(Customer.class),该方法会去domain所在路径下寻找Customer.hbm.xml映射文件,源代码如下:
 
?
1
2
3
4
5
public Configuration addClass(Class persistentClass) throws MappingException {
         String mappingResourceName = persistentClass.getName().replace( '.' , '/' ) + ".hbm.xml" ;
         LOG.readingMappingsFromResource( mappingResourceName );
         return addResource( mappingResourceName, persistentClass.getClassLoader() );
     }

persistentClass.getName()得到类的完整名称,对于本工程来说是com.ligang.domain.Customer,最终得到的mappingResourceName 为com/ligang/domain/Customer.hbm.xml。 
如果该映射文件不像放到domain类的同一个目录下,想放到类路径下的hibernate/mapping/文件夹下则可以使用config.addResource("hibernate/mapping/Customer.hbm.xml"),这里路径的前面不能含有/,文件名可以随意取,没有要求。 

加载配置文件说完了,然后继续下面的步骤,开始创建SessionFactory了。
 
?
1
sessionFactory=config.buildSessionFactory();

对于上述方法,已是过时的方法,推荐的方法是buildSessionFactory(serviceRegistry),网上有很多的说法是,使用如下代码替代:  
?
1
ServiceRegistry serviceRegistry= new ServiceRegistryBuilder().applySettings(config.getProperties()).buildServiceRegistry();

但是目前对于4.3.6.Final的hibernate来说ServiceRegistryBuilder已经过时,替换类则是StandardServiceRegistryBuilder,可以使用如下方案:  
?
1
2
ServiceRegistry serviceRegistry= new StandardServiceRegistryBuilder().applySettings(config.getProperties()).build();
sessionFactory=config.buildSessionFactory(serviceRegistry);

我们再看下config.buildSessionFactory()的源码:  
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public SessionFactory buildSessionFactory() throws HibernateException {
         Environment.verifyProperties( properties );
         ConfigurationHelper.resolvePlaceHolders( properties );
         final ServiceRegistry serviceRegistry =  new StandardServiceRegistryBuilder()
                 .applySettings( properties )
                 .build();
         setSessionFactoryObserver(
                 new SessionFactoryObserver() {
                     @Override
                     public void sessionFactoryCreated(SessionFactory factory) {
                     }
 
                     @Override
                     public void sessionFactoryClosed(SessionFactory factory) {
                         ( (StandardServiceRegistryImpl) serviceRegistry ).destroy();
                     }
                 }
         );
         return buildSessionFactory( serviceRegistry );
     }

它内部也是使用了StandardServiceRegistryBuilder,所以说上述方案还没config.buildSessionFactory()这个过时的方案好。对于ServiceRegistry这一块,日后再详细研究,至少我感觉hibernate这一块设计的不是很好。我理解的好的设计,对于用户来说是简单易用的,尽量对外不要暴漏内部的一些机制,而这里ServiceRegistry则会让一个初学者一头雾水,需要花费更多的时间去理解内部的机制。 

有了SessionFactory,我们便可以获取Session,然后进行增删改查了,建立了如下的单元测试类如下:
 
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@RunWith (JUnit4ClassRunner. class )
@ContextConfiguration (locations = "file:src/main/webapp/WEB-INF/mvc-servlet.xml" )
public class CustomerDaoTest {
     
     @Autowired
     private HibernateDao hibernateDao;
     
     @Test
     public void testAdd(){
         Customer customer= new Customer();
         customer.setName( "小明" );
         customer.setEmail( "123456789@qq.com" );
         Timestamp t= new Timestamp(System.currentTimeMillis());
         customer.setRegisteredTime(t);
         Session session=hibernateDao.getSession();
         Transaction tx=session.beginTransaction();
         session.save(customer);
         tx.commit();
         session.close();
     }
}

运行单元测试方法,便可以看到成功的进行了增添操作。 

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
5月前
|
SQL 缓存 Java
Hibernate - 检索策略入门与详解
Hibernate - 检索策略入门与详解
31 0
|
5月前
|
SQL Java 数据库连接
Hibernate - 基础入门详解
Hibernate - 基础入门详解
50 1
|
SQL Java 数据库连接
hibernate入门学习笔记
hibernate入门学习笔记
64 0
|
SQL XML Java
Mybatis01入门+使用和配置+面试题mybatis与hibernate的区别+ssm与ssh2开发对比
Mybatis01入门+使用和配置+面试题mybatis与hibernate的区别+ssm与ssh2开发对比
Mybatis01入门+使用和配置+面试题mybatis与hibernate的区别+ssm与ssh2开发对比
|
存储 SQL Java
Hibernate入门实例
Hibernate是一个基于jdbc的开源的持久化框架,是一个优秀的ORM实现,它很大程度的简化了dao层编码工作。Hibernate对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。
Hibernate入门实例
|
SQL 设计模式 缓存
【框架】[Hibernate]构架知识点详解入门与测试实例
【框架】[Hibernate]构架知识点详解入门与测试实例
101 0
【框架】[Hibernate]构架知识点详解入门与测试实例
|
Oracle Java 关系型数据库
Hibernate入门这一篇就够了(四)
Hibernate入门这一篇就够了
132 0
Hibernate入门这一篇就够了(四)
|
SQL Java 数据库连接
Hibernate入门这一篇就够了(三)
Hibernate入门这一篇就够了
103 0
Hibernate入门这一篇就够了(三)
|
XML Java 数据库连接
Hibernate入门这一篇就够了(二)
Hibernate入门这一篇就够了
134 0
Hibernate入门这一篇就够了(二)
|
SQL XML 前端开发
Hibernate入门这一篇就够了(一)
Hibernate入门这一篇就够了
159 0
Hibernate入门这一篇就够了(一)