慢來比較快,虛心學技術
Ⅰ、Hibernate架構體系分析
先來了解一下Hibernate的框架體系,下圖爲官方Hibernate簡要體系結構:
Hibernate通過持久化對象Persistent Objects(PO)對數據庫進行操作,底層數據庫操作 對於應用程序來說是透明的,應用程序無需關心JDBC操作,底層數據庫連接、數據庫訪問實現、事務控制,而是直接以面向對象方式進行持久層的操作。
Hibernate詳細的框架體系如下:
- SessionFactory:****是依賴於ConnectionProvider的會話和客戶端工廠。 它擁有數據的二級緩存(可選)。 org.hibernate.SessionFactory接口提供了工廠方法來獲取Session的對象。(實現了****EntityManagerFactory****接口)
- Session:****應用程序與持久層之間交互操作的一個單線程對象。所有的持久化對象必須在Session管理下才能進行持久化操作。它底層封裝了JDBC連接,是Transaction工廠。(實現了****EntityManager****接口)
- 持久化對象(PO):系統創建的POJO實例,一旦與特定的Session關聯,並對應數據表的指定記錄,該對象就處於持久化狀態。
- 事務(Transaction):代表一次原子操作,Hibernate事務是對底層具體的JDBC,JTA以及CORBA事務的抽象。
- 連接提供者(ConnectionProvider):生成JDBC連接的工廠,通過抽象將應用程序與底層的DataSource或DriverManager隔離開。
- 事務工廠(TransactionFactory):它是一個事務工廠,是一個可選項。
如下是一次數據庫請求操作的執行過程:
①應用程序調用Configuration讀取配置文件(映射文件和hibernate.propertise),並據此生成SessionFactory工廠對象。
②SessionFactory生產Session操作對象,通過Session對象對數據庫執行CRUD操作,同時生成Transaction對象
③如果Session執行操作正常,Transaction提交事務將結果真正生成至數據庫,如果操作異常,則執行事務回滾
Ⅱ、Spring整合使用Hibernate
①引入依賴:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--logback日誌實現引入-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.1.7</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-access</artifactId>
<version>1.1.7</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.7</version>
</dependency>
<!--slf4j日誌門面引入-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.7</version>
</dependency>
<!--引入alibaba的數據庫連接池-->
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!--引入Spring支持-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<!--引入Spring事務-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<!--引入Spring對ORM框架的支持依賴-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<!--引入Hibernate支持-->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.9.0</version>
</dependency>
<!--引入數據庫驅動-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
②編寫實體類:BaseBean
@Data//lombok註解,默認添加setter,getter方法
@ToString//lombok註解,默認改寫toString()方法
public class BaseBean {
private Integer id;
private String name;
private Integer age;
}
③編寫實體類映射文件:BaseBean.hbm.xml,將BaseBean實體類與數據庫表basebean關聯映射
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">-->
<!-- Generated 2016-3-15 16:30:05 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
<class name="com.my.spring.bean.BaseBean" table="basebean">
<id name="id" type="java.lang.Integer" column="id">
<generator class="native" />
</id>
<property name="name" type="java.lang.String" column="name"/>
<property name="age" type="java.lang.Integer" column="age"/>
</class>
</hibernate-mapping>
映射文件和實體類位置如下:
④編寫數據庫資源文件:dataSource.properties
#指定數據庫驅動
jdbc.driver = com.mysql.jdbc.Driver
#指定數據庫url
jdbc.url = jdbc:mysql://localhost:3306/spring
#指定數據庫用戶
jdbc.username = spring
#指定數據庫用戶密碼
jdbc.password = spring
#指定使用的數據庫連接池
druid.dataSource=com.alibaba.druid.pool.DruidDataSource
#指定最大活躍連接數
druid.maxActive=10
#指定等待連接超時時間,單位毫秒
druid.maxWait=10000
#指定間隔掃描連接時間,檢測需要關閉的空閒連接,單位是毫秒
druid.timeBetweenEvictionRunsMillis=60000
⑤編寫Spring配置文件:application.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/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--開啓 spring註解掃描-->
<context:annotation-config/>
<!--配置組件掃描範圍-->
<context:component-scan base-package="com.my.spring"></context:component-scan>
<!-- 導入資源文件 -->
<context:property-placeholder location="classpath:datasource.properties"/>
<!--配置數據庫連接池-->
<bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
<property name="maxActive" value="${druid.maxActive}"></property>
<property name="maxWait" value="${druid.maxWait}"></property>
<property name="timeBetweenEvictionRunsMillis" value="${druid.timeBetweenEvictionRunsMillis}"></property>
</bean>
<!--配置Hibernate下的SessionFactory-->
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean" lazy-init="false">
<!--注入數據庫-->
<property name="dataSource" ref="dataSource" />
<!-- //加載實體類的映射文件位置及名稱 -->
<property name="mappingLocations" value="classpath*:/com/my/spring/bean/*.hbm.xml"></property>
<!--配置hibernate的主配置屬性-->
<property name="hibernateProperties">
<props>
<!--是否顯示執行sql-->
<prop key="hibernate.show_sql">true</prop>
<!--數據庫表策略-->
<prop key="hibernate.hbm2ddl.auto">update</prop>
<!--數據庫方言-->
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
</props>
</property>
</bean>
<!-- 配置Spring聲明式事務 -->
<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="dataSource" ref="dataSource"></property>
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!--開啓註解事務-->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
⑥編寫數據庫操作接口和實現類:BaseBeanRepository.java&BaseBeanRepositoryImpl.java
public interface BaseRepository {
/**
* 保存記錄
* @param baseBean
* @return
*/
void save(BaseBean baseBean);
/**
* 獲取所有記錄
* @return
*/
List<BaseBean> findAll();
/**
* 獲取指定id記錄
* @param id
* @return
*/
BaseBean findOne(Integer id);
}
@Repository
public class BaseRepositoryImpl implements BaseRepository {
//注入sessionFactory,用於獲取session
@Autowired
private SessionFactory sessionFactory;
//獲取session
public Session getSession(){
return sessionFactory.getCurrentSession();
}
@Override
public void save(BaseBean baseBean) {
this.getSession().saveOrUpdate(baseBean);
}
@Override
public List<BaseBean> findAll() {
String hql = "FROM BaseBean";
Query query = this.getSession().createQuery(hql);
return query.list();
}
@Override
public BaseBean findOne(Integer id) {
String hql = "FROM BaseBean Where id=?";
Query query = this.getSession().createQuery(hql).setParameter(0,id);
return (BaseBean) query.uniqueResult();
}
}
⑦編寫邏輯處理接口和實現類:BaseService.java&BaseServiceImpl.java
public interface BaseService {
/**
* 保存記錄
* @param baseBean
* @return
*/
void save(BaseBean baseBean);
/**
* 獲取所有記錄
* @return
*/
List<BaseBean> findAll();
/**
* 獲取指定id記錄
* @param id
* @return
*/
BaseBean findOne(Integer id);
}
@Component
@Transactional(rollbackFor = {RuntimeException.class})
public class BaseServiceImpl implements BaseService {
//注入baseRepository操作類
@Autowired
private BaseRepository baseRepository;
@Override
public void save(BaseBean baseBean) {
this.baseRepository.save(baseBean);
}
@Override
public List<BaseBean> findAll() {
return this.baseRepository.findAll();
}
@Override
public BaseBean findOne(Integer id) {
return this.baseRepository.findOne(id);
}
}
⑧編寫測試類
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:application.xml"})
public class AppTest
{
@Autowired
private BaseService baseService;
@Autowired
private ApplicationContext applicationContext;
@Test
public void testHibernate() throws SQLException {
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames){
System.out.println(beanDefinitionName);
}
}
@Test
public void testSave(){
BaseBean baseBean = new BaseBean();
baseBean.setName("hibernate bean");
baseBean.setAge(50);
this.baseService.save(baseBean);
}
@Test
public void testFindAll(){
List<BaseBean> list = this.baseService.findAll();
if(null==list||list.isEmpty()){
System.out.println("空表");
}else{
for (BaseBean baseBean : list){
System.out.println(baseBean.toString());
}
}
}
}
⑨測試結果:
執行testHibernate()
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.annotation.internalPersistenceAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
baseRepositoryImpl
baseServiceImpl
org.springframework.context.support.PropertySourcesPlaceholderConfigurer#0
dataSource
sessionFactory
transactionManager
org.springframework.transaction.config.internalTransactionalEventListenerFactory
org.springframework.aop.config.internalAutoProxyCreator
org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0
org.springframework.transaction.interceptor.TransactionInterceptor#0
org.springframework.transaction.config.internalTransactionAdvisor
執行 testSave()
2019-03-18 11:34:31.537 DEBUG org.hibernate.SQL - insert into basebean (name, age) values (?, ?)
Hibernate: insert into basebean (name, age) values (?, ?)
2019-03-18 11:34:31.556 DEBUG org.hibernate.id.IdentifierGeneratorHelper - Natively generated identity: 2
執行testFindAll()
2019-03-18 11:37:22.901 DEBUG org.hibernate.SQL - select basebean0_.id as id1_0_, basebean0_.name as name2_0_, basebean0_.age as age3_0_ from basebean basebean0_
Hibernate: select basebean0_.id as id1_0_, basebean0_.name as name2_0_, basebean0_.age as age3_0_ from basebean basebean0_
BaseBean(id=1, name=hibernate bean, age=50)
BaseBean(id=2, name=hibernate bean, age=50)