Hibernate是什么?
Hibernate与MyBatis都是流行的持久层开发框架,只不过Hibernate是全自动ORM框架,不需要关心sql编写。
Hibernate 是一个高性能的对象/关系映射(ORM)持久化存储和查询的服务,不仅负责从Java类到数据库表的映射 (还包括从Java数据类型到SQL数据类型的映射),还提供了面向对象的数据查询检索机制,从而极大地缩短了手动处理SQL和JDBC上的开发时间。 同时,Hibernate还实现了JPA规范,在SpringBoot中,JPA的默认实现就是使用的Hibernate。
JPA和Hibernate?
JPA
JPA(Java Persistence API)是Sun官方提出的Java持久化规范,它为Java开发人员提供了一种对象/关系映射工具来管理Java应用中的关系数据。
可以通过注解或者XML描述【对象-关系表】之间的映射关系,并将实体对象持久化到数据库中。
JPA仅仅是一种规范,也就是说JPA仅仅定义了一些接口,而接口是需要实现才能工作的。所以底层需要某种实现,而Hibernate就是实现了JPA接口的ORM框架。
Hibernate
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的ORM框架。 Hibernate可以自动生成SQL语句、自动执行,从而使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。
实际上,JPA规范制定过程中就是借鉴了Hibernate等这些开源的持久框架,也就是说Hibernate的出现比JPA还要早些。
在Hibernate中使用的注解就是JPA注解,Hibernate实现了JPA规范。
Spring Data JPA
spirng data jpa是spring提供的一套简化JPA开发的框架,按照约定好的【方法命名规则】写dao层接口,就可以在不写接口实现的情况下,实现对数据库的访问和操作。同时提供了很多除了CRUD之外的功能,如分页、排序、复杂查询等等。
Spring Data JPA 可以理解为 JPA 规范的再次封装抽象,底层还是使用了 Hibernate 的 JPA 技术实现。
SpringData
Spring Data 是持久层通用解决方案,支持 关系型数据库 Oracle、MySQL、非关系型数据库NoSQL、Map-Reduce 框架、云基础数据服务 、搜索服务。
Spring Data是一个开源框架而Spring Data JPA是这个框架的模块。
一、新建SpringBoot项目
在pom.xml中引入maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.17</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
</dependency>
创建数据库
create table books
(
book_id int(5) primary key auto_increment,
title varchar(200),
category varchar(100)
)
INSERT INTO `books` (`book_id`, `title`, `category`) VALUES
(1, '123', 'qwe'),
(2, '456', 'asd'),
(3, '789', 'zxc');
配置文件application.yml
spring:
jpa:
properties:
hibernate:
dialect: org.hibernate.dialect.MySQLDialect
new_generator_mappings: false
format_sql: true
datasource:
url: jdbc:mysql://localhost:3306/ss?serverTimezone=UTC&useSSL=false&autoReconnect=true&tinyInt1isBit=false&useUnicode=true&characterEncoding=utf8
username: root
password: 123qwe
创建如图以下包
在config下编写数据源配置
@Configuration
@EnableTransactionManagement(order = 2)
public class DataSourceConfig {
@Resource
private DruidProperties druidProperties;
/**
* 单数据源连接池配置
*/
@Bean
public DruidDataSource singleDatasource() {
DruidDataSource dataSource = new DruidDataSource();
druidProperties.config(dataSource);
return dataSource;
}
}
@Component
@ConfigurationProperties(prefix = "spring.datasource")
public class DruidProperties {
private String url;
private String username;
private String password;
private String driverClassName = "com.mysql.cj.jdbc.Driver";
private Integer initialSize = 10;
private Integer minIdle = 3;
private Integer maxActive = 60;
private Integer maxWait = 60000;
private Boolean removeAbandoned = true;
private Integer removeAbandonedTimeout = 180;
private Integer timeBetweenEvictionRunsMillis = 60000;
private Integer minEvictableIdleTimeMillis = 300000;
private String validationQuery = "SELECT 'x'";
private Boolean testWhileIdle = true;
private Boolean testOnBorrow = false;
private Boolean testOnReturn = false;
private Boolean poolPreparedStatements = true;
private Integer maxPoolPreparedStatementPerConnectionSize = 50;
private String filters = "stat";
public void config(DruidDataSource dataSource) {
dataSource.setDbType(JdbcConstants.MYSQL);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
dataSource.setDriverClassName(driverClassName);
// 定义初始连接数
dataSource.setInitialSize(initialSize);
// 最小空闲
dataSource.setMinIdle(minIdle);
// 定义最大连接数
dataSource.setMaxActive(maxActive);
// 获取连接等待超时的时间
dataSource.setMaxWait(maxWait);
// 超过时间限制是否回收
dataSource.setRemoveAbandoned(removeAbandoned);
// 超过时间限制多长
dataSource.setRemoveAbandonedTimeout(removeAbandonedTimeout);
// 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
// 配置一个连接在池中最小生存的时间,单位是毫秒
dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
// 用来检测连接是否有效的sql,要求是一个查询语句
dataSource.setValidationQuery(validationQuery);
// 申请连接的时候检测
dataSource.setTestWhileIdle(testWhileIdle);
// 申请连接时执行validationQuery检测连接是否有效,配置为true会降低性能
dataSource.setTestOnBorrow(testOnBorrow);
// 归还连接时执行validationQuery检测连接是否有效,配置为true会降低性能
dataSource.setTestOnReturn(testOnReturn);
// 打开PSCache,并且指定每个连接上PSCache的大小
dataSource.setPoolPreparedStatements(poolPreparedStatements);
dataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
// 属性类型是字符串,通过别名的方式配置扩展插件,常用的插件有:
// 监控统计用的filter:stat
// 日志用的filter:log4j
// 防御SQL注入的filter:wall
try {
dataSource.setFilters(filters);
} catch (SQLException e) {
e.printStackTrace();
}
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getDriverClassName() {
return driverClassName;
}
public void setDriverClassName(String driverClassName) {
this.driverClassName = driverClassName;
}
public Integer getInitialSize() {
return initialSize;
}
public void setInitialSize(Integer initialSize) {
this.initialSize = initialSize;
}
public Integer getMinIdle() {
return minIdle;
}
public void setMinIdle(Integer minIdle) {
this.minIdle = minIdle;
}
public Integer getMaxActive() {
return maxActive;
}
public void setMaxActive(Integer maxActive) {
this.maxActive = maxActive;
}
public Integer getMaxWait() {
return maxWait;
}
public void setMaxWait(Integer maxWait) {
this.maxWait = maxWait;
}
public Integer getTimeBetweenEvictionRunsMillis() {
return timeBetweenEvictionRunsMillis;
}
public void setTimeBetweenEvictionRunsMillis(Integer timeBetweenEvictionRunsMillis) {
this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
}
public Integer getMinEvictableIdleTimeMillis() {
return minEvictableIdleTimeMillis;
}
public void setMinEvictableIdleTimeMillis(Integer minEvictableIdleTimeMillis) {
this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
}
public String getValidationQuery() {
return validationQuery;
}
public void setValidationQuery(String validationQuery) {
this.validationQuery = validationQuery;
}
public Boolean getTestWhileIdle() {
return testWhileIdle;
}
public void setTestWhileIdle(Boolean testWhileIdle) {
this.testWhileIdle = testWhileIdle;
}
public Boolean getTestOnBorrow() {
return testOnBorrow;
}
public void setTestOnBorrow(Boolean testOnBorrow) {
this.testOnBorrow = testOnBorrow;
}
public Boolean getTestOnReturn() {
return testOnReturn;
}
public void setTestOnReturn(Boolean testOnReturn) {
this.testOnReturn = testOnReturn;
}
public Boolean getPoolPreparedStatements() {
return poolPreparedStatements;
}
public void setPoolPreparedStatements(Boolean poolPreparedStatements) {
this.poolPreparedStatements = poolPreparedStatements;
}
public Integer getMaxPoolPreparedStatementPerConnectionSize() {
return maxPoolPreparedStatementPerConnectionSize;
}
public void setMaxPoolPreparedStatementPerConnectionSize(Integer maxPoolPreparedStatementPerConnectionSize) {
this.maxPoolPreparedStatementPerConnectionSize = maxPoolPreparedStatementPerConnectionSize;
}
public String getFilters() {
return filters;
}
public void setFilters(String filters) {
this.filters = filters;
}
public Boolean getRemoveAbandoned() {
return removeAbandoned;
}
public void setRemoveAbandoned(Boolean removeAbandoned) {
this.removeAbandoned = removeAbandoned;
}
public Integer getRemoveAbandonedTimeout() {
return removeAbandonedTimeout;
}
public void setRemoveAbandonedTimeout(Integer removeAbandonedTimeout) {
this.removeAbandonedTimeout = removeAbandonedTimeout;
}
}
在entity下创建实体类
@Entity
@Table(name = "books")
@Data
public class Book implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "book_id")
private int bookId;
@Column(name = "title")
private String title;
@Column(name = "category")
private String category;
}
创建在repository下创建Dao层接口和在impl下创建Dao实现类
public interface BookDao {
List<Book> getAllBooks();
Book getBookById(int bookId);
void addBook(Book book);
void updateBook(Book book);
void deleteBook(int bookId);
boolean bookExists(String title,String category);
}
@Repository
public class IBookDao implements BookDao {
@PersistenceContext
private EntityManager entityManager;
@Override
public List<Book> getAllBooks() {
String sql = "FROM Book as book ORDER BY book.bookId";
return (List<Book>)entityManager.createQuery(sql).getResultList();
}
@Override
public Book getBookById(int bookId) {
return entityManager.find(Book.class,bookId);
}
@Override
public void addBook(Book book) {
entityManager.persist(book);
}
@Override
public void updateBook(Book book) {
Book book1 = getBookById(book.getBookId());
book1.setTitle(book.getTitle());
book1.setCategory(book.getCategory());
entityManager.flush();
entityManager.clear();
}
@Override
public void deleteBook(int bookId) {
entityManager.remove(getBookById(bookId));
}
@Override
public boolean bookExists(String title, String category) {
String sql = "FROM Book as book WHERE book.title=?0 and book.category=?1";
int count = entityManager.createQuery(sql)
.setParameter(0,title)
.setParameter(1,category)
.getResultList().size();
return count > 0;
}
}
创建业务层Service,注入BookDao
@Service
public class BookService {
@Autowired
private BookDao bookDao;
public Book getBookById(int bookId){
Book book= bookDao.getBookById(bookId);
return book;
}
public List<Book> getAllBooks(){
return bookDao.getAllBooks();
}
public synchronized boolean addBook(Book book){
if(bookDao.bookExists(book.getTitle(),book.getCategory())){
return false;
}else {
bookDao.addBook(book);
return true;
}
}
public void updateBook(Book book){
bookDao.updateBook(book);
}
public void deleteBook(int bookId){
bookDao.deleteBook(bookId);
}
}
测试类 编写测试代码
再上图中测试类下编写以下代码
@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
public class HibernateApplicationTests {
@Autowired
private BookService bookService;
@Test
@Rollback(false)
public void contextLoads() {
Book book = bookService.getBookById(1);
assertThat(book.getTitle(),is("123"));
List<Book> list = bookService.getAllBooks();
assertThat(list,notNullValue());
assertThat(list.size(), is(3));
boolean flag = bookService.addBook(book);
assertThat(flag, is(false));
book.setTitle("012");
bookService.updateBook(book);
Book book1 = bookService.getBookById(1);
System.out.println(book1);
assertThat(book1.getTitle(), is("012"));
bookService.deleteBook(1);
Book article2 = bookService.getBookById(1);
assertThat(article2, nullValue());
}
}
依次执行上面测试代码中的增删改查。根据数据库和控制台输出查看结果是否测试通过。简单的集成Hibernate已经完成。更多可以了解JPA复杂语句查询以及根据实体类自动创建数据库。