美文网首页JavaJAVA学习记录Java 杂谈
《Spring实战》-第十一章:利用对象-关系映射持久化数据(S

《Spring实战》-第十一章:利用对象-关系映射持久化数据(S

作者: 廖小明的赖胖子 | 来源:发表于2019-03-28 23:33 被阅读0次

    慢来比较快,虚心学技术

    Ⅰ、Hibernate架构体系分析

    先来了解一下Hibernate的框架体系,下图为官方Hibernate简要体系结构:

    Hibernate通过持久化对象Persistent Objects(PO)对数据库进行操作,底层数据库操作 对于应用程序来说是透明的,应用程序无需关心JDBC操作,底层数据库连接、数据库访问实现、事务控制,而是直接以面向对象方式进行持久层的操作。

    Hibernate详细的框架体系如下:

    1. SessionFactory:****是依赖于ConnectionProvider的会话和客户端工厂。 它拥有数据的二级缓存(可选)。 org.hibernate.SessionFactory接口提供了工厂方法来获取Session的对象。(实现了****EntityManagerFactory****接口)
    2. Session:****应用程序与持久层之间交互操作的一个单线程对象。所有的持久化对象必须在Session管理下才能进行持久化操作。它底层封装了JDBC连接,是Transaction工厂。(实现了****EntityManager****接口)
    3. 持久化对象(PO):系统创建的POJO实例,一旦与特定的Session关联,并对应数据表的指定记录,该对象就处于持久化状态。
    4. 事务(Transaction):代表一次原子操作,Hibernate事务是对底层具体的JDBC,JTA以及CORBA事务的抽象。
    5. 连接提供者(ConnectionProvider):生成JDBC连接的工厂,通过抽象将应用程序与底层的DataSource或DriverManager隔离开。
    6. 事务工厂(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)
    

    相关文章

      网友评论

        本文标题:《Spring实战》-第十一章:利用对象-关系映射持久化数据(S

        本文链接:https://www.haomeiwen.com/subject/ernhbqtx.html