《Spring实战》-第十一章:利用对象-关系映射持久化数据(Spring整合Hibernate)
慢来比较快,虚心学技术
Ⅰ、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
①引入依赖:
[code]<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
[code]@Data//lombok注解,默认添加setter,getter方法 @ToString//lombok注解,默认改写toString()方法 public class BaseBean { private Integer id; private String name; private Integer age; }
③编写实体类映射文件:BaseBean.hbm.xml,将BaseBean实体类与数据库表basebean关联映射
[code]<?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
[code]#指定数据库驱动 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
[code]<?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
[code]public interface BaseRepository { / 1c140 ** * 保存记录 * @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
[code]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); } }
⑧编写测试类
[code]@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()
[code]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()
[code]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()
[code]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)
- 《Spring实战》-第十一章:利用对象-关系映射持久化数据(Spring整合Spring Data JPA)
- spring(11)使用对象-关系映射持久化数据
- Spring学习笔记之使用对象-关系映射持久化数据
- 第11章-使用对象-关系映射持久化数据
- ssh框架hibernate 2持久化对象和关系关联映射
- Hibernate关联映射-数据对象三种关系
- Hibernate知识整理4---关系映射及持久化对象
- Hibernate的核心对象关系映射
- Hibernate映射对象之间的多种关系
- Hibernate的核心对象关系映射
- JPA保存数据时报持久化对象异常:PersistenceException: org.hibernate.PersistentObjectException
- java 利用反射 从数据库取出数据对象list 类似hibernate
- hibernate 与 spring整合,SessionFactory初始化hibernate,Session数据的增删改查
- Hibernate数据查询 利用关联关系操纵对象 Hibernate事务 Hibernate的Cache管理
- Hibernate之 对象/关系数据库映射基础(Basic O/R Mapping)
- Hibernate对象关系映射----继承映射
- Spring 整合 Hibernate5 时的方式、引入关系映射文件的多种方式
- Hibernate数据映射关系
- 用Maven整合SpringMVC+Spring+Hibernate 框架,实现简单的插入数据库数据功能
- ORM框架Hibernate (三) 对象到关系多对一映射