Hibernate与MyBatis都是流行的持久层开发框架,前一遍介绍了怎样在SpringBoot中集成MyBatis,本篇来介绍如何集成Hibernate作为DAO层。
Hibernate 是一个高性能的对象/关系映射(ORM)持久化存储和查询的服务,不仅负责从Java类到数据库表的映射
(还包括从Java数据类型到SQL数据类型的映射),还提供了面向对象的数据查询检索机制,从而极大地缩短了手动处理SQL和JDBC上的开发时间。
同时,Hibernate还实现了JPA规范,在SpringBoot中,JPA的默认实现就是使用的Hibernate。
 
JPA和Hibernate 在讲解如何在SpringBoot中使用Hibernate框架之前,先要弄清几个基本概念以及它们之间的关系。
JPA 
Hibernate 
Spring Data 
Spring Data JPA 
 
JPA JPA(Java Persistence API)是Sun官方提出的Java持久化规范,它为Java开发人员提供了一种对象/关系映射工具来管理Java应用中的关系数据。
上面已经描述很清楚了,JPA是一种规范和标准,也就是类似于Java中的接口,由Sun公司官方定义,但是并没有指定谁来实现。
现在几个主要的JPA实现技术有Hibernate、EclipseLink、OpenJPA等。
Hibernate Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的ORM框架。
Hibernate可以自动生成SQL语句、自动执行,从而使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。
实际上,JPA规范制定过程中就是借鉴了Hibernate等这些开源的持久框架,也就是说Hibernate的出现比JPA还要早些。
在Hibernate中使用的注解就是JPA注解,Hibernate实现了JPA规范。
Spring Data Spring Data是一个用于简化数据库访问,并支持云服务的开源框架。其主要目标是使得数据库的访问变得方便快捷,
并支持map-reduce框架和云计算数据服务。此外,它还支持基于关系型数据库的数据服务,如Oracle RAC等。
所以Spring Data本身就是一个开源的框架。
Spring Data JPA 上面说过Spring Data是一个开源框架,在这个框架中Spring Data JPA只是这个框架中的一个模块。
它可以极大的简化JPA的写法,可以在几乎不用写实现的情况下,实现对数据的访问和操作。除了CRUD外,还包括如分页、排序等一些常用的功能。
好了,现在你应该对这些概念有一个基本认识了,接下来进入正题,演示如何在SpringBoot中使用Hibernate。
maven依赖 第一步添加maven依赖:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <dependency >     <groupId > org.springframework.boot</groupId >      <artifactId > spring-boot-starter-data-jpa</artifactId >  </dependency > <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <version > ${mysql-connector.version}</version > <scope > runtime</scope > </dependency > <dependency > <groupId > com.alibaba</groupId > <artifactId > druid</artifactId > <version > ${druid.version}</version > </dependency > 
 
注意,使用mysql数据库来演示的话还要添加数据库驱动包,另外还添加了druid连接池。
准备数据库 如何安装mysql,配置用户名和密码之类我就不在这里讲了,请自行google。
下面是我的schema.sql文件,创建一个pos数据库,并创建一个article表,插入几条初始数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 CREATE DATABASE IF NOT  EXISTS  `pos` default  charset utf8 COLLATE  utf8_general_ci; SET FOREIGN_KEY_CHECKS= 0 ; USE `pos`; CREATE  TABLE  IF NOT  EXISTS  `articles`(     `article_id` int  (     5  ) NOT  NULL  AUTO_INCREMENT,     `title` varchar  (     200  ) NOT  NULL ,     `category` varchar  (     100  ) NOT  NULL ,     PRIMARY  KEY (     `article_id` )     ) ENGINE= InnoDB AUTO_INCREMENT= 1  DEFAULT  CHARSET= utf8 COMMENT= '文章表' ; INSERT  INTO  `articles` (`article_id`, `title`, `category`)VALUES  (1 , 'Java Concurrency' , 'Java' ),       (2 , 'Hibernate HQL ' , 'Hibernate' ),        (3 , 'Spring MVC with Hibernate' , 'Spring' ); 
 
注意,Hibernate可以根据实体类自动创建表,本篇我不介绍这个功能,还是手动创建表结构。
修改配置文件 数据库创建好后,修改application.yml配置文件,新增如下数据库连接配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 spring:   profiles:      active:  dev    jpa:      properties:        hibernate:          dialect:  org.hibernate.dialect.MySQLDialect          new_generator_mappings:  false          format_sql:  true    datasource:      url:  jdbc:mysql://127.0.0.1:3306/pos?serverTimezone=UTC&useSSL=false&autoReconnect=true&tinyInt1isBit=false&useUnicode=true&characterEncoding=utf8      username:  root      password:  123456  
 
实体类 article表对应的实体类如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Entity @Table(name = "articles") public  class  Article  implements  Serializable  {    private  static  final  long  serialVersionUID  =  1L ;     @Id      @GeneratedValue(strategy = GenerationType.AUTO)      @Column(name = "article_id")      private  int  articleId;     @Column(name = "title")      private  String title;     @Column(name = "category")      private  String category;      } 
 
DAO设计 先创建一个DAO的接口类:
1 2 3 4 5 6 7 8 9 10 11 12 13 public  interface  IArticleDAO  {    List<Article> getAllArticles () ;     Article getArticleById (int  articleId) ;     void  addArticle (Article article) ;     void  updateArticle (Article article) ;     void  deleteArticle (int  articleId) ;     boolean  articleExists (String title, String category) ; } 
 
然后写一个实现类,在这类中注入EntityManager
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 @Repository public  class  ArticleDAO  implements  IArticleDAO  {    @PersistenceContext      private  EntityManager entityManager;     @Override      public  Article getArticleById (int  articleId)  {         return  entityManager.find(Article.class, articleId);     }     @SuppressWarnings("unchecked")      @Override      public  List<Article> getAllArticles ()  {         String  hql  =  "FROM Article as atcl ORDER BY atcl.articleId" ;         return  (List<Article>) entityManager.createQuery(hql).getResultList();     }     @Override      public  void  addArticle (Article article)  {         entityManager.persist(article);     }     @Override      public  void  updateArticle (Article article)  {         Article  artcl  =  getArticleById(article.getArticleId());         artcl.setTitle(article.getTitle());         artcl.setCategory(article.getCategory());         entityManager.flush();     }     @Override      public  void  deleteArticle (int  articleId)  {         entityManager.remove(getArticleById(articleId));     }     @Override      public  boolean  articleExists (String title, String category)  {         String  hql  =  "FROM Article as atcl WHERE atcl.title = ? and atcl.category = ?" ;         int  count  =  entityManager.createQuery(hql).setParameter(0 , title)                 .setParameter(1 , category).getResultList().size();         return  count > 0 ;     } } 
 
业务Service 编写业务逻辑Service类,注入DAO类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 @Service public  class  ArticleService  {    @Resource      private  IArticleDAO articleDAO;     public  Article getArticleById (int  articleId)  {         Article  obj  =  articleDAO.getArticleById(articleId);         return  obj;     }     public  List<Article> getAllArticles ()  {         return  articleDAO.getAllArticles();     }     public  synchronized  boolean  addArticle (Article article)  {         if  (articleDAO.articleExists(article.getTitle(), article.getCategory())) {             return  false ;         } else  {             articleDAO.addArticle(article);             return  true ;         }     }     public  void  updateArticle (Article article)  {         articleDAO.updateArticle(article);     }     public  void  deleteArticle (int  articleId)  {         articleDAO.deleteArticle(articleId);     } } 
 
编写测试用例 OK,一切写完后,就来编写我们的测试用例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 @RunWith(SpringRunner.class) @SpringBootTest public  class  ApplicationTests  {    private  static  final  Logger  log  =  LoggerFactory.getLogger(ApplicationTests.class);     @Resource      private  ArticleService articleService;          @Test      public  void  test ()  {         Article  article  =  articleService.getArticleById(1 );         assertThat(article.getTitle(), is("Java Concurrency" ));         List<Article> list = articleService.getAllArticles();         assertThat(list, notNullValue());         assertThat(list.size(), is(3 ));         boolean  flag  =  articleService.addArticle(article);         assertThat(flag, is(false ));         article.setTitle("Python Concurrency" );         articleService.updateArticle(article);         Article  article1  =  articleService.getArticleById(1 );         assertThat(article1.getTitle(), is("Python Concurrency" ));         articleService.deleteArticle(1 );         Article  article2  =  articleService.getArticleById(1 );         assertThat(article2, nullValue());     } } 
 
上面先查询id=1的文章,看看标题是否为Java Concurrency,然后查询所有文章列表,之后更新文章标题后再次查询看看是否更新成功。
最后删除这篇文章,再次查询结果为null。
运行结果green bar,测试通过。
更多Hibernate相关文档,请参考 官网  。
GitHub源码 springboot-hibernate