[Spring] - Spring + Hibernate

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] - Spring + Hibernate

[Spring] - Spring + Hibernate

 


 

 

项目结构:

[Spring] - Spring + Hibernate

 

Spring所需要用到的Jar包:

[Spring] - Spring + Hibernate

 

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

[Spring] - Spring + Hibernate

你可能感兴趣的:(Hibernate)