• [Spring]


    Spring整合Hibernate,花了很长时间研究,其中碰到的比较多问题。

    使用的是Spring3.0+Hibernate4.1.6,Spring整合最新版本的Hibernate4.5,会抛些奇奇怪怪的异常。这个官网有说明。

    先上代码。

    spring的xml配置:springContext.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:aop="http://www.springframework.org/schema/aop"
                 xmlns:tx="http://www.springframework.org/schema/tx"
                 xsi:schemaLocation="http://www.springframework.org/schema/beans
                         http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
                         http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
                         http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
    
        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName" value="com.mysql.jdbc.Driver" />
            <property name="url" value="jdbc:mysql://127.0.0.1/test" />
            <property name="username" value="root" />
            <property name="password" value="root" />
        </bean>
    
        <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
            <property name="dataSource" ref="dataSource" />
            <property name="packagesToScan">
                <list>
                    <value>com.my.entity</value>
                </list>
            </property>
            <property name="hibernateProperties">
                <value>
                    hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
                    hibernate.hbm2ddl.auto=update
                    hibernate.show_sql=true
                    hibernate.format_sql=false
                    hibernate.cache.use_second_level_cache=true
                    hibernate.cache.use_query_cache=false
                    hibernate.cache.provider_class=org.hibernate.cache.internal.NoCacheProvider
                    hibernate.current_session_context_class= org.springframework.orm.hibernate4.SpringSessionContext
                </value>
            </property>
        </bean>
        <bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
            <property name="sessionFactory" ref="sessionFactory" />
        </bean>
        
        <context:component-scan base-package="com.my" />
        
        <tx:annotation-driven transaction-manager="txManager" />
        <tx:advice id="txAdvice" transaction-manager="txManager">
            <tx:attributes>
                <tx:method name="*" read-only="true"/>
                <tx:method name="add*" propagation="REQUIRED" rollback-for="Exception"/>
                <tx:method name="create*" propagation="REQUIRED" rollback-for="Exception"/>
                <tx:method name="insert*" propagation="REQUIRED" rollback-for="Exception"/>
                <tx:method name="update*" propagation="REQUIRED" rollback-for="Exception"/>
                <tx:method name="delete*" propagation="REQUIRED" rollback-for="Exception"/>
                <tx:method name="remove*" propagation="REQUIRED" rollback-for="Exception"/>
            </tx:attributes>
        </tx:advice>
        
        <aop:config>
          <aop:pointcut id="allServiceMethods" expression="execution(* com.my.service.*.*(..))"/>
          <aop:advisor advice-ref="txAdvice" pointcut-ref="allServiceMethods"/>
        </aop:config>
    
    </beans>

    逐一解释下这个XML,这是最关键的地方:

    1、dataSource,这里所使用的是spring自带的org.springframework.jdbc.datasource.DriverManagerDataSource,但这个一般用于个人开发或非并发小项目是可以的,如果用于大型的项目,需要把它替换使用proxool。proxool与spring配置,可以网上搜索下。

    2、sessionFactory,里头有个property值为packagesToScan,应该是hibernate所使用的annotation object(即POJO)。使用这个packagesToScan,会自动扫描代码,无需一个个写了。

    3、txManager,这是transation管理bean,意思是把声明一个transation bean,以待注入。

    4、<context:component-scan base-package="com.my" />,这句是spring使用annotation做注入,基于com.my的命名空间下的所有包和类扫描

    5、<tx:annotation-driven transaction-manager="txManager" />,声明一个annotation的transation,让AOP使用。

    6、txAdvice,声明一个spring AOP的advice,其意思是内容中定义的attributes对应的方法是否需要开启或禁用transation,以及rollback条件。

    7、<aop:config/>是spring的AOP,将txAdvice切入到对应的pointcut中。

    补充:

    因为测试时使用的是MySql,在测试transation时,发现怎么也不能回滚。原来是MySql数据库要把表引擎修改为InnoDB类型才支持事务。之前使用的是绿色版的MySql,设置了很久也没设置成功,最后去官网下了个安装版的5.7版本,装上默就是InnoDB。-_-#

    贴代码:

    DAO:

    package com.my.dao;
    
    import javax.annotation.Resource;
    
    import org.hibernate.SessionFactory;
    import org.springframework.stereotype.Repository;
    
    import com.my.entity.Account;
    
    @Repository
    public abstract class AccountDaoFactory {
        @Resource
        private SessionFactory sessionFactory;
        
        public SessionFactory getSessionFactory() {
            return sessionFactory;
        }
    
        public void setSessionFactory(SessionFactory sessionFactory) {
            this.sessionFactory = sessionFactory;
        }
        
        /*
         * Fin account by id
         */
        public abstract Integer findAccount(Integer accountID);
        
        /*
         * Add account
         */
        public abstract Account add(String name);
        
        /*
         * Delete account
         */
        public abstract boolean delete(long id);
    }
    package com.my.dao.mysql;
    
    import org.hibernate.Session;
    import org.springframework.stereotype.Repository;
    
    import com.my.entity.Account;
    
    @Repository(value = "accountDao")
    public class AccountDao extends com.my.dao.AccountDaoFactory {
        /*
         * Find account by account id
         */
        @Override
        public Integer findAccount(Integer accountID) {
            return accountID;
        }
    
        @Override
        public Account add(String name) {
            Session session = super.getSessionFactory().getCurrentSession();
    
            Account account = new Account();
            account.setName(name);
            session.save(account);
            return account;
        }
    
        @Override
        public boolean delete(long id) {
            Session session = super.getSessionFactory().getCurrentSession();
            Account account = (Account) session.get(Account.class, id);
            session.delete(account);
            return true;
        }
    }

    Service:

    package com.my.service;
    
    import javax.annotation.Resource;
    
    import com.my.dao.AccountDaoFactory;
    import com.my.entity.Account;
    
    public abstract class AccountServiceFactory {
        @Resource(name="accountDao")
        protected AccountDaoFactory accountDao;
        
        public AccountDaoFactory getAccountDAO() {
            return accountDao;
        }
    
        public void setAccountDAO(AccountDaoFactory accountDAO) {
            this.accountDao = accountDAO;
        }
        
        /*
         * Find account by id
         */
        public abstract Integer findAccount(Integer accountID);
        
        /*
         * Add account
         */
        public abstract Account add(String name);
        
        /*
         * Delete account
         */
        public abstract boolean delete(long id);
        
        /*
         * Add and Delete account, transaction test.
         */
        public abstract boolean addAndDelete(String name);
    }
    package com.my.service.mysql;
    
    import org.springframework.stereotype.Service;
    
    import com.my.entity.Account;
    import com.my.service.AccountServiceFactory;
    
    @Service(value="accountService")
    public class AccountService extends AccountServiceFactory {
    
        @Override
        public Integer findAccount(Integer accountID) {
            return accountDao.findAccount(accountID);
        }
    
        @Override
        public Account add(String name) {
            return accountDao.add(name);
        }
    
        @Override
        public boolean delete(long id) {
            return accountDao.delete(id);
        }
    
        @Override
        public boolean addAndDelete(String name) {
            Account account = accountDao.add(name);
            boolean result = accountDao.delete(account.getId());
            return result;
        }
        
    }

    Controller:

    package com.my.controller;
    
    import javax.annotation.Resource;
    
    import org.springframework.stereotype.Controller;
    
    import com.my.entity.Account;
    import com.my.service.AccountServiceFactory;
    
    @Controller
    public class SpringController {
        @Resource(name="accountService")
        private AccountServiceFactory accountService;
        
        public AccountServiceFactory getAccount() {
            return accountService;
        }
    
        public void setAccount(AccountServiceFactory account) {
            this.accountService = account;
        }
        
        public Integer findAccount(Integer accountID){
            return accountService.findAccount(accountID);
        }
        
        public Account add(String name){
            return accountService.add(name);
        }
        
        public boolean delete(long id){
            return accountService.delete(id);
        }
        
        public boolean addAndDelete(String name){
            return accountService.addAndDelete(name);
        }
    }

    POJO entity:

    package com.my.entity;
    
    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 = "account")
    public class Account {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "id")
        private long id;
    
        @Column(name = "name", length = 200)
        private String name;
    
        public long getId() {
            return id;
        }
    
        public void setId(long id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }

    JUnit测试:

    package com.my.controller;
    
    import static org.junit.Assert.*;
    
    import org.junit.Before;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class SpringControllerTest {
        private SpringController springController;
        private ApplicationContext context;
    
        @Before
        public void setUp() throws Exception {
            context = new ClassPathXmlApplicationContext("springContext.xml");
            // Use class load
            springController = (SpringController)context.getBean(SpringController.class);
        }
    
        @Test
        public void testFindAccount() {
            String name = "Robin";
            boolean result = springController.addAndDelete(name);
            assertTrue(result);
        }
    
    }

    输出结果:


    项目结构:

    Spring所需要用到的Jar包:

    Hibernate4.1.6所需要用到的Jar包:

  • 相关阅读:
    JqGrid常用示例
    jqGrid无刷新分页,添加行按钮
    C#两个实体之间相同属性的映射
    Log4Net日志记录
    C#压缩图片
    ASP.Net MVC4.0+无刷新分页
    世界各个国家中英文sql建表
    ASP.NET多语言
    分布式事务处理中的幂等性
    分布式事务前瞻-接口幂等性
  • 原文地址:https://www.cnblogs.com/HD/p/3966971.html
Copyright © 2020-2023  润新知