hibernate在实际应用中,很少单独使用的,基本都是和spring一起使用,这里介绍如何整合spring4+hibernate5。hibernate与spring整合,配置文件hibernate.cfg.xml就不需要了,配置信息直接提到spring配置文件里面,hibernate的sessionFactory交给spring容器管理,不再单独通过Configuration来构建。
整合首先需要一个数据源dataSource,这里使用HikariCP数据源,他的数据库连接池性能很好,另外,需要配置sessionFactory,因为要考虑事务,所以需要配置事务控制管理器,然后就是需要事务控制的service层切点。
介绍完了整合的思路,然后直接构建maven工程,引入相关配置,开始干活。
pom.xml
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.version>4.3.13.RELEASE</spring.version>
<hibernate.version>5.2.17.Final</hibernate.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>2.7.9</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
</dependencies>
jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///hibernate4?useUnicode=true&useSSL=false&characterEncoding=UTF-8
jdbc.username=hadoop
jdbc.password=hadoop
hibernate.maxPoolSize=50
hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
hibernate.show_sql=true
hibernate.format_sql=true
hibernate.hbm2ddl.auto=update
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="hibernateProperties">
<value>
hibernate.dialect=${hibernate.dialect}
hibernate.show_sql=${hibernate.show_sql}
hibernate.format_sql=${hibernate.format_sql}
hibernate.hbm2ddl.auto=${hibernate.hbm2ddl.auto}
hibernate.cache.use_second_level_cache=false
hibernate.cache.use_query_cache=false
hibernate.jdbc.fetch_size=50
hibernate.jdbc.batch_size=50
</value>
</property>
<property name="packagesToScan" value="com.xxx.spring.hibernate.entity"></property>
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="find*" propagation="REQUIRED" read-only="true"/>
<tx:method name="get*" propagation="REQUIRED" read-only="true"/>
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="delete*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut expression="execution( * com.xxx.spring.hibernate.service.*.*(..))" id="tx-pointcut"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="tx-pointcut"/>
</aop:config>
<context:component-scan base-package="com.xxx.spring.hibernate" />
</beans>
Book.java
package com.xxx.spring.hibernate.entity;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="xx_book")
public class Book implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
@Column(length=20)
private String title;
private String description;
//@Column(precision=10,scale=2)
@Column(columnDefinition="double(10,2)")
private Double price;
@Column(name="publishdate")
private Date publishDate;
@Column(name="createdate")
private Date createDate;
@Column(name="modifydate")
private Date modifyDate;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public Date getPublishDate() {
return publishDate;
}
public void setPublishDate(Date publishDate) {
this.publishDate = publishDate;
}
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
public Date getModifyDate() {
return modifyDate;
}
public void setModifyDate(Date modifyDate) {
this.modifyDate = modifyDate;
}
@Override
public String toString() {
return "Book [id=" + id + ", title=" + title + ", price=" + price + "]";
}
}
BaseDao.java
package com.xxx.spring.hibernate.dao;
import java.io.Serializable;
import java.util.List;
public interface BaseDao<T> {
T findById(Serializable key);
void save(T entity);
void update(T entity);
void delete(Serializable key);
List<T> findAll();
}
BookDao.java
package com.xxx.spring.hibernate.dao;
import com.xxx.spring.hibernate.entity.Book;
public interface BookDao extends BaseDao<Book> {
}
BaseDaoImpl.java
package com.xxx.spring.hibernate.dao.impl;
import java.io.Serializable;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;
import org.springframework.beans.factory.annotation.Autowired;
import com.xxx.spring.hibernate.dao.BaseDao;
public abstract class BaseDaoImpl<T> implements BaseDao<T> {
public abstract Class<T> getEntityClass();
@Autowired
private SessionFactory sessionFactory;
public Session getSession() {
return sessionFactory.getCurrentSession();
}
@Override
public void save(T entity) {
getSession().persist(entity);
}
@Override
public void update(T entity) {
getSession().update(entity);
}
@Override
public T findById(Serializable key) {
return getSession().get(getEntityClass(), key);
}
@Override
public void delete(Serializable key) {
getSession().delete(findById(key));
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public List<T> findAll() {
String hql = "from "+getEntityClass().getName();
Query query = getSession().createQuery(hql);
return query.list();
}
}
BookDaoImpl.java
package com.xxx.spring.hibernate.dao.impl;
import org.springframework.stereotype.Repository;
import com.xxx.spring.hibernate.dao.BookDao;
import com.xxx.spring.hibernate.entity.Book;
@Repository
public class BookDaoImpl extends BaseDaoImpl<Book> implements BookDao {
@Override
public Class<Book> getEntityClass() {
return Book.class;
}
}
BookService.java
package com.xxx.spring.hibernate.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.xxx.spring.hibernate.dao.BookDao;
import com.xxx.spring.hibernate.entity.Book;
@Service
public class BookService {
@Autowired
private BookDao bookDao;
public void save(Book entity) {
bookDao.save(entity);
}
public void update(Book entity) {
bookDao.update(entity);
}
public void delete(Integer id) {
bookDao.delete(id);
}
public List<Book> findAll(){
return bookDao.findAll();
}
public Book findById(Integer id) {
return bookDao.findById(id);
}
}
编写好了相关代码,现在通过单元测试来测试BookService增删改查接口:
package com.xxx.spring.hibernate;
import java.util.Date;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.xxx.spring.hibernate.entity.Book;
import com.xxx.spring.hibernate.service.BookService;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations= {"classpath:applicationContext.xml"})
public class AppTest {
@Autowired
private BookService bookService;
@Test
public void save() {
Book book = new Book();
book.setTitle("java in action");
book.setDescription("a book about java language programing");
book.setPrice(19.8d);
book.setPublishDate(new Date());
book.setCreateDate(new Date());
book.setModifyDate(new Date());
bookService.save(book);
}
@Test
public void query() {
List<Book> list = bookService.findAll();
for(Book book:list) {
System.out.println(book);
}
}
@Test
public void update() {
Book book = bookService.findById(2);
System.out.println(book);
book.setDescription("this is a java programing book");
book.setModifyDate(new Date());
bookService.update(book);
}
@Test
public void delete() {
Integer id = 1;
bookService.delete(id);
}
}
测试保存方法打印信息:
新增的数据:
运行修改方法的打印信息:
修改之后的数据:
执行查询和删除方法这里就不演示了。
hibernate与spring的整合思路,大体就是这样,dataSource,sessionFactory,transactionManager,txAdvice,aop等等配置清楚就好了,如果事务管理也是用注解的话,会更加的简单。
dao,service层的实体bean均没有在applicationContext.xml配置文件中体现,我们通过在类上使用@Service,@Repository等注解已经把bean声明了,通过<context:component-scan base-package="com.xxx.spring.hibernate" />这一句配置就告诉spring容器,在首次加载的时候,在指定的包路径下扫描实体类,并实例化。通过@Autowired注解,我们将类中需要的实体属性,也注入到了相应的实体中。这就是配置文件中,为什么没有dao,service层的实体类bean的配置的原因。