• ssh,hibernate动态映射多表


    [From] http://www.07net01.com/2016/01/1172051.html


    最近在做OA系统(ssh),一直在想如何把框架架得更完善,此前已经在框架里集成springMVC,读写分离(这个在另一篇文章里会有说明怎么做),这几天在想如果是大数据,要分表要怎么来弄,不可能每一个表都写一个实体来映射,这样太不灵活,也不现实!

    oa考勤本来数据不多,如果分表一般以年份来分表。今天研究的是以用户来分表。

    网上找了些资料,说是可以用NamingStrategy来实现动态映射表名。

    发现sessionFactory里面有个namingStrategy属性可以注入,这个东东就是hibernate在表映射时要用的,关系啥的都放在这个里面,只要重写它就行。不过只有在容器启动时才会加载这个,也就是只会执行一次,以后就算动态设置了namingStrategy也不会再加载改变映射关系了,那会就是一个sessionFactory只能在启动时对应一个namingStrategy;如此要想对应多个相同表映射就须得要有多个sessionFactory才行;

    可是spring并没有提供像AbstractRoutingDataSource动态数据源这样的接口给我们用,那怎么办,只能自己写一个了,既然我们要多个sessionFactory,但我们的底层dao里是只注入一个sessionFactory,那么我们就模仿动态数据源一样写个路由DynamicSessionFactory继承sessionFactory,并且提供一个动态getHibernateSessionFactory的方法,然后写个实现DynamicSessionFactoryImpl重写sessionFactory里面的方法,让里面的方法在取sessionFactory时全部通过getHibernateSessionFactory得到,而getHibernateSessionFactory就是动态根据我们的设置来取sessionFactory的了,这样就实现动态取不同的sessionFactory了。

    getHibernateSessionFactory靠ThreadLocal的特性,给当前线程设置sessionFactory的bean名称,然后在取时就拿这个bean名称取对应的bean就行了。

    在配好这些后,当时想的是用spring的aop来拦截service层的方法来进行动态设置bean名称,在实践后发现这样做在单表或者说是在一次请求只调一个service方法时且不懒加载时才可以,当一个action请求有两个以上service方法时,就完了,每调一个方法sessionFactory就会重新设置一下,这样session就一定会关闭了,这样在调完方法查出数据后如果去懒加载get数据就会发现没有session,就报错了(collection is not associated with any session)。所以我们不能在service层做文章,得在action层甚至是filter里做动态设置才行。

    发现在web.xml里有个org.springframework.orm.hibernate4.support.OpenSessionInViewFilter,这个的用处就是为了解决一个请求里session统一的问题的,不过这里虽然配置了,但一在service层动态设置sessionFactory后,每次都给改变了。所以我们只要在这个filter里来动态设置sessionFactory就行了,这样每次一个请求就设置一个sessionFactory,直到完成。实现:就是写一个MyOpenSessionInViewFilter去继承OpenSessionInViewFilter然后重写它的lookupSessionFactory方法,在每次请求lookupSessionFactory动态设上自己要的sessionFactory就行了。

    这样设置完成后测试发现可以达到效果,可点着点着就发现问题了,一到使用多线程(在生成多人的排班考勤时我都是使用多线程来生成的)时,就会报当前线程的session为空。仔细想想也不难理解,每次设置时我都是只设置了请求的这条线程的话,也就是只有主线程是有了的长时间session存在的,当用多线程时,每一条新线程都在拿sessionFactory时都会调ThreadLocal当前线程的存的sessionFactory的名称来取,这样当然就取不到了,想着就把主线程的sessionFactory的名称也传进子线程设置在子线程这样就有了吧,结果发现是有了,sessionFactory取对了,可是在取当前session时又报错取不到了。这又是怎么回事呢,于是又想着把主线程那个session也传进去试试,发现传进去,哎,不报错了,是取得到了,我去,却发现它不在事务里了。至此得整理下思路,一个线程一个session的话,那多线程中的子线程就不能再用那个session了,得是它自己启动一个session事务,可想着那些service方法本来我就是有设置事务的呀!然后去看看事务的配置文件,哎哟喂,事务配的是org.springframework.orm.hibernate4.HibernateTransactionManager,里面配的是路由sessionFactory,原来是事务没有动态呀,这样每次调用时都是同一个,没有动态给多个sessionFactory都设置事务。于是写一个动态事务DynamicTransactionManager去继承HibernateTransactionManager,并重写getSessionFactory和getDataSource方法,这样就实现了动态事务的动态sessionFactory了。然后再测试下多线程的,搞定!

    历时两天多,终于搞定了!

    平时没怎么写文章,文字表达能力不好,凑合着看吧,以后得多练练

    下面上一下代码吧!

    动态表名实现类:

    /**
     * 动态表名
     */
    import <a target=_blank href="http://www.07net01.com/tags-Java-0.html" target="_blank" class="infotextkey" style="box-sizing: border-box; color: rgb(66, 139, 202); background: transparent;">Java</a>.text.DecimalFormat;
    import java.util.ArrayList;
    
    import org.hibernate.cfg.DefaultNamingStrategy;
    
    public class TNamingStrategy extends DefaultNamingStrategy {
    
    	 /**
    	 *
    	 */
    	private static final long serial<a target=_blank href="http://www.07net01.com/tags-version-0.html" target="_blank" class="infotextkey" style="box-sizing: border-box; color: rgb(66, 139, 202); background: transparent;">version</a>UID = 1L;
    
        private static final DecimalFormat df = new DecimalFormat();
        private static ArrayList<String> rollingTables = new ArrayList<String>();
        private String suffix;//表后缀
        static {
            rollingTables.add("KQ_ATTENDANCE");//有哪些表需要多个映射的就在这里add进去
            rollingTables.add("KQ_DUTY_ROSTER");
            df.applyPattern("00");
        }
    /*    @Override
        public String classToTableName(String className) {
         // TODO Auto-generated method stub
         return tableName(StringHelper.unqualify(className).toUpperCase());
        } */
        /**
         *
         *
         *  class里显式设置了表名,就调用 tableName
         *  没有显示就调用  classToTableName
         */
        public String tableName(String tableName) {
            String stroeTable = tableName;
            // 对指定的表名计算实际<a target=_blank href="http://www.07net01.com/storage_networking/" target="_blank" class="infotextkey" style="box-sizing: border-box; color: rgb(66, 139, 202); background: transparent;">存储</a>表名
            if (rollingTables.contains(tableName.toUpperCase())&&suffix!=null) {
                stroeTable += "_" + suffix;
                <a target=_blank href="http://www.07net01.com/tags-system-0.html" target="_blank" class="infotextkey" style="box-sizing: border-box; color: rgb(66, 139, 202); background: transparent;">system</a>.out.println("store record into [" + stroeTable + "]");
            }
    
            return stroeTable;
        }
    	public String getSuffix() {
    		return suffix;
    	}
    	public void setSuffix(String suffix) {
    		this.suffix = suffix;
    	}
    
    
    
    	}

    当前线程保存sessonFactory bean名称:

    public abstract class CustomerContextHolder {
    
        private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
    
        public static void setCustomerType(String customerType) {
            contextHolder.set(customerType);
        }
    
        public static String getCustomerType() {
        	if(contextHolder.get()==null)
        	{
        		System.out.println("空啦");
    
        	 setCustomerType("master");
        	}
            return contextHolder.get();
        }
    
        public static void clearCustomerType() {
            contextHolder.remove();
        }
    
    
    }

    路由sessionFactory:

     
    import org.hibernate.SessionFactory;
    
    
    public <a target=_blank href="http://www.07net01.com/tags-interface-0.html" target="_blank" class="infotextkey" style="box-sizing: border-box; color: rgb(66, 139, 202); background: transparent;">interface</a> DynamicSessionFactory extends SessionFactory {
    
        public SessionFactory getHibernateSessionFactory();
    }

    路由sessionFactory实现:

    import java.io.Serializable;
    import java.sql.Connection;
    import java.util.Map;
    import java.util.Set;
    
    import javax.naming.NamingException;
    import javax.naming.Reference;
    
    import org.hibernate.Cache;
    import org.hibernate.HibernateException;
    import org.hibernate.Session;
    import org.hibernate.SessionBuilder;
    import org.hibernate.SessionFactory;
    import org.hibernate.StatelessSession;
    import org.hibernate.StatelessSessionBuilder;
    import org.hibernate.TypeHelper;
    import org.hibernate.engine.spi.FilterDefinition;
    import org.hibernate.metadata.ClassMetadata;
    import org.hibernate.metadata.CollectionMetadata;
    import org.hibernate.stat.Statistics;
    
    /**
     * <b>function:</b> 动态sessionFactory实现
    
     * @version 1.0
     */
    @SuppressWarnings({ "unchecked", "deprecation" })
    public class DynamicSessionFactoryImpl implements DynamicSessionFactory {
    
        private static final long serialVersionUID = 5384069312247414885L;
    
        private Map<Object, SessionFactory> targetSessionFactorys;
        private SessionFactory defaultTargetSessionFactory;
    
    
    
        /**
         *
         * <b>function:</b> 重写这个方法,这里最关键
    
         */
        @Override
        public SessionFactory getHibernateSessionFactory() {
            SessionFactory targetSessionFactory = targetSessionFactorys.get(CustomerContextHolder.getCustomerType());
          //  System.out.println("CustomerContextHolder.getCustomerType():"+CustomerContextHolder.getCustomerType());
         //   System.out.println("targetSessionFactory:"+targetSessionFactory);
            if (targetSessionFactory != null) {
                return targetSessionFactory;
            } else if (defaultTargetSessionFactory != null) {
                return defaultTargetSessionFactory;
            }
            return null;
        }
    
        public SessionFactory getObject()
            {
              return this.getHibernateSessionFactory();
         }
        @Override
        public void close() throws HibernateException {
            this.getHibernateSessionFactory().close();
        }
    
        @Override
        public boolean containsFetchProfileDefinition(String s) {
            return this.getHibernateSessionFactory().containsFetchProfileDefinition(s);
        }
    
        @Override
        public void evict(Class clazz) throws HibernateException {
            this.getHibernateSessionFactory().evict(clazz);
        }
    
        @Override
        public void evict(Class clazz, Serializable serializable) throws HibernateException {
            this.getHibernateSessionFactory().evict(clazz, serializable);
        }
    
        @Override
        public void evictCollection(String s) throws HibernateException {
            this.getHibernateSessionFactory().evictCollection(s);
        }
    
        @Override
        public void evictCollection(String s, Serializable serializable) throws HibernateException {
            this.getHibernateSessionFactory().evictCollection(s, serializable);
        }
    
        @Override
        public void evictEntity(String entity) throws HibernateException {
            this.getHibernateSessionFactory().evictEntity(entity);
        }
    
        @Override
        public void evictEntity(String entity, Serializable serializable) throws HibernateException {
            this.getHibernateSessionFactory().evictEntity(entity, serializable);
        }
    
        @Override
        public void evictQueries() throws HibernateException {
            this.getHibernateSessionFactory().evictQueries();
        }
    
        @Override
        public void evictQueries(String queries) throws HibernateException {
            this.getHibernateSessionFactory().evictQueries(queries);
        }
    
        @Override
        public Map<String, ClassMetadata> getAllClassMetadata() {
            return this.getHibernateSessionFactory().getAllClassMetadata();
        }
    
        @Override
        public Map getAllCollectionMetadata() {
            return this.getHibernateSessionFactory().getAllClassMetadata();
        }
    
        @Override
        public Cache getCache() {
            return this.getHibernateSessionFactory().getCache();
        }
    
        @Override
        public ClassMetadata getClassMetadata(Class clazz) {
            return this.getHibernateSessionFactory().getClassMetadata(clazz);
        }
    
        @Override
        public ClassMetadata getClassMetadata(String classMetadata) {
            return this.getHibernateSessionFactory().getClassMetadata(classMetadata);
        }
    
        @Override
        public CollectionMetadata getCollectionMetadata(String collectionMetadata) {
            return this.getHibernateSessionFactory().getCollectionMetadata(collectionMetadata);
        }
    
        @Override
        public Session getCurrentSession() throws HibernateException {
            return this.getHibernateSessionFactory().getCurrentSession();
        }
    
        @Override
        public Set getDefinedFilterNames() {
            return this.getHibernateSessionFactory().getDefinedFilterNames();
        }
    
        @Override
        public FilterDefinition getFilterDefinition(String definition) throws HibernateException {
            return this.getHibernateSessionFactory().getFilterDefinition(definition);
        }
    
        @Override
        public Statistics getStatistics() {
            return this.getHibernateSessionFactory().getStatistics();
        }
    
        @Override
        public TypeHelper getTypeHelper() {
            return this.getHibernateSessionFactory().getTypeHelper();
        }
    
        @Override
        public boolean isClosed() {
            return this.getHibernateSessionFactory().isClosed();
        }
    
        @Override
        public Session openSession() throws HibernateException {
            return this.getHibernateSessionFactory().openSession();
        }
    
        @Override
        public StatelessSession openStatelessSession() {
            return this.getHibernateSessionFactory().openStatelessSession();
        }
    
        @Override
        public StatelessSession openStatelessSession(Connection connection) {
            return this.getHibernateSessionFactory().openStatelessSession(connection);
        }
    
        @Override
        public Reference getReference() throws NamingException {
            return this.getHibernateSessionFactory().getReference();
        }
    
        public void setTargetSessionFactorys(Map<Object, SessionFactory> targetSessionFactorys) {
            this.targetSessionFactorys = targetSessionFactorys;
        }
    
        public void setDefaultTargetSessionFactory(SessionFactory defaultTargetSessionFactory) {
            this.defaultTargetSessionFactory = defaultTargetSessionFactory;
        }
    
    
    	@Override
    	public SessionFactoryOptions getSessionFactoryOptions() {
    
    		return this.getHibernateSessionFactory().getSessionFactoryOptions();
    	}
    
    
    	@Override
    	public SessionBuilder withOptions() {
    
    		return this.getHibernateSessionFactory().withOptions();
    	}
    
    
    	@Override
    	public StatelessSessionBuilder withStatelessOptions() {
    
    		return this.getHibernateSessionFactory().withStatelessOptions();
    	}
    
    
    }

    动态的事务管理器:

    import javax.sql.DataSource;
    
    import org.hibernate.SessionFactory;
    import org.springframework.orm.hibernate4.HibernateTransactionManager;
    import org.springframework.orm.hibernate4.SessionFactoryUtils;
    
    
    /**
     * <b>function:</b> 重写HibernateTransactionManager事务管理器,实现自己的动态的事务管理器
    
     * @version 1.0
     */
    public class DynamicTransactionManager extends HibernateTransactionManager {
    
        private static final long serialVersionUID = -4655721479296819154L;
    
        /**
         * @see org.springframework.orm.hibernate4.HibernateTransactionManager#getDataSource()
         * <b>function:</b> 重写
    
         */
        @Override
        public DataSource getDataSource() {
            return SessionFactoryUtils.getDataSource(getSessionFactory());
        }
    
        /**
         * @see org.springframework.orm.hibernate4.HibernateTransactionManager#getSessionFactory()
         * <b>function:</b> 重写
         */
        @Override
        public SessionFactory getSessionFactory() {
            DynamicSessionFactory dynamicSessionFactory = (DynamicSessionFactory) super.getSessionFactory();
            SessionFactory hibernateSessionFactory = dynamicSessionFactory.getHibernateSessionFactory();
            return hibernateSessionFactory;
        }
    }

    自己的OpenSessionInViewFilter,为的是一个请求一个session并且有选择的设定sessionFactory:

    import java.io.IOException;
    
    import javax.servlet.FilterChain;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.springframework.orm.hibernate4.SessionFactoryUtils;
    import org.springframework.orm.hibernate4.SessionHolder;
    import org.springframework.orm.hibernate4.support.AsyncRequestInterceptor;
    import org.springframework.orm.hibernate4.support.OpenSessionInViewFilter;
    import org.springframework.transaction.support.TransactionSynchronizationManager;
    import org.springframework.web.context.WebApplicationContext;
    import org.springframework.web.context.request.async.WebAsyncManager;
    import org.springframework.web.context.request.async.WebAsyncUtils;
    import org.springframework.web.context.support.WebApplicationContextUtils;
    
    import sy.model.base.frame.SessionInfo;
    import sy.model.base.frame.Syuser;
    import sy.util.base.ConfigUtil;
    /**
     * 自己的OpenSessionInViewFilter,为的是一个请求一个session并且有选择的设定sessionFactory
     * @author miraclerz
     *
     */
    public class MyOpenSessionInViewFilter extends OpenSessionInViewFilter {
    	private HttpServletRequest request;
    
    	@Override
    	protected SessionFactory lookupSessionFactory() {
    
    		WebApplicationContext wac = WebApplicationContextUtils
    				.getRequiredWebApplicationContext(getServletContext());
    		String sessionFactoryName = getSessionFactoryBeanName();
    
    		 //动态设置sessionFactory名称了
    		 CustomerContextHolder.setCustomerType("master");
    		 
    
    		DynamicSessionFactoryImpl dynamicSessionFactoryImpl = wac.getBean(
    				sessionFactoryName, DynamicSessionFactoryImpl.class);
    
    		return dynamicSessionFactoryImpl.getObject();
    	}
    
    	 
    
    }
    

    上一下配置文件:

    <?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:aop="http://www.springframework.org/schema/aop" xmlns:c="http://www.springframework.org/schema/c" xmlns:cache="http://www.springframework.org/schema/cache" xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:lang="http://www.springframework.org/schema/lang" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p" xmlns:task="http://www.springframework.org/schema/task" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
    		http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd
    		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
    		http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
    		http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
    		http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd
    		http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
    		http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd
    		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
    		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
    
     <!--配置  -->
    
        <!-- 加载properties配置文件 -->
        <bean id="propertyConfigurer"
            class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
            <property name="locations">
                <list>
                    <value>classpath:switchSessionFactory/sessionFactoryJdbc.properties</value>
                </list>
            </property>
        </bean>
       <bean id="sessionFactoryDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
    			<property name="driverClassName" value="http://520shuijing.iteye.com/blog/${sessionFactory.jdbc.driverClassName}" />
    	        <property name="url" value="http://520shuijing.iteye.com/blog/${sessionFactory.jdbc.url}" />
    	        <property name="username" value="http://520shuijing.iteye.com/blog/${sessionFactory.jdbc.username}" />
    	        <property name="password" value="http://520shuijing.iteye.com/blog/${sessionFactory.jdbc.password}" />
    			<!-- 初始化连接大小 -->
    		<property name="initialSize" value="http://520shuijing.iteye.com/blog/1" />
    		<!-- 连接池最大使用连接数量 -->
    		<property name="maxActive" value="http://520shuijing.iteye.com/blog/300" />
    		<!-- 连接池最小空闲 -->
    		<property name="minIdle" value="http://520shuijing.iteye.com/blog/0" />
    		<!-- 获取连接最大等待时间 -->
    		<property name="maxWait" value="http://520shuijing.iteye.com/blog/60000" />
    
    		<!-- <property name="poolPreparedStatements" value="http://520shuijing.iteye.com/blog/true" /> <property name="maxPoolPreparedStatementPerConnectionSize" value="http://520shuijing.iteye.com/blog/33" /> -->
    
    		<property name="validationQuery" value="http://520shuijing.iteye.com/blog/${sessionFactory.hibernate.validationQuery}" />
    		<!-- 检测有效性 -->
    		<property name="testOnBorrow" value="http://520shuijing.iteye.com/blog/true" />
    		<property name="testOnReturn" value="http://520shuijing.iteye.com/blog/false" />
    		<property name="testWhileIdle" value="http://520shuijing.iteye.com/blog/true" />
    
    		<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
    		<property name="timeBetweenEvictionRunsMillis" value="http://520shuijing.iteye.com/blog/19000" />
    		<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
    		<property name="minEvictableIdleTimeMillis" value="http://520shuijing.iteye.com/blog/19000" />
    
    		<!-- 打开removeAbandoned功能 -->
    		<property name="removeAbandoned" value="http://520shuijing.iteye.com/blog/true" />
    		<!-- 1800秒,也就是30分钟   -->
    		<property name="removeAbandonedTimeout" value="http://520shuijing.iteye.com/blog/1800" />
    		<!-- 关闭abanded连接时输出错误日志 -->
    		<property name="logAbandoned" value="http://520shuijing.iteye.com/blog/true" />
    
            <!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->
    		<property name="poolPreparedStatements" value="http://520shuijing.iteye.com/blog/true" />
    		<property name="maxPoolPreparedStatementPerConnectionSize" value="http://520shuijing.iteye.com/blog/20" />
    		<!-- 监控<a target=_blank href="http://www.07net01.com/tags-%E6%95%B0%E6%8D%AE%E5%BA%93-0.html" target="_blank" class="infotextkey" style="box-sizing: border-box; color: rgb(66, 139, 202); background: transparent;">数据库</a> -->
    		<!-- <property name="filters" value="http://520shuijing.iteye.com/blog/mergeStat" /> -->
    		<property name="filters" value="http://520shuijing.iteye.com/blog/stat" />
    	</bean>
    
    
      <!-- 配置sessionFactory -->
        <bean id="masterSessionFactory"
           class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
            <property name="dataSource" ref="sessionFactoryDataSource"></property>
             <property name="hibernateProperties">
                <props>
    				<prop key="hibernate.hbm2ddl.auto">${switch_session_factory_hibernate.hbm2ddl.auto}</prop>
    				<prop key="hibernate.dialect">${switch_session_factory_hibernate.dialect}</prop>
    				<prop key="hibernate.show_sql">${switch_session_factory_hibernate.show_sql}</prop>
    				<prop key="hibernate.format_sql">${switch_session_factory_hibernate.format_sql}</prop>
    				<prop key="hibernate.use_sql_comments">${switch_session_factory_hibernate.use_sql_comments}</prop>
    			    <prop key="current_session_context_class">thread</prop>
    			</props>
            </property>
    
           <!-- 自动扫描注解方式配置的hibernate类文件 -->
    		<property name="<a target=_blank href="http://www.07net01.com/tags-package-0.html" target="_blank" class="infotextkey" style="box-sizing: border-box; color: rgb(66, 139, 202); background: transparent;">package</a>sToScan">
    			<list>
    				<value>sy.model.base</value>
    			</list>
    		</property>
    
        </bean>
    
     <import resource="classpath:switchSessionFactory/moreSessionFactory/*.xml" />
    
        <!-- 配置sessionFactory 多个的实现-->
        <bean id="sessionFactory"
           class="sy.datasource.sessionFactory.DynamicSessionFactoryImpl">
              <property name="targetSessionFactorys">
                <map>
                    <entry value-ref="masterSessionFactory" key="master"/>
     
                    <entry value-ref="s_adminSessionFactory" key="s_admin"/>
                </map>
              </property>
             <property name="defaultTargetSessionFactory" ref="masterSessionFactory"/>
        </bean>
    
    
        <!-- 配置事务管理器 -->
        <bean id="switch_session_factory_transactionManager"
             class="sy.datasource.sessionFactory.DynamicTransactionManager">
           <property name="sessionFactory" ref="sessionFactory"></property>
    
        </bean>
    
    
    
    
    <!-- 拦截器方式配置事物 -->
    	<tx:advice id="switch_session_factory_txAdvice" transaction-manager="switch_session_factory_transactionManager">
    		<tx:attributes>
    			<tx:method name="save*" propagation="REQUIRED" />
    			<tx:method name="<a target=_blank href="http://www.07net01.com/tags-update-0.html" target="_blank" class="infotextkey" style="box-sizing: border-box; color: rgb(66, 139, 202); background: transparent;">update</a>*" propagation="REQUIRED" />
    			<tx:method name="saveOrUpdate*" propagation="REQUIRED" />
    			<tx:method name="delete*" propagation="REQUIRED" />
    			<tx:method name="grant*" propagation="REQUIRED" />
    
    			<tx:method name="init*" propagation="REQUIRED" />
    
    			<tx:method name="*" propagation="REQUIRED" read-only="true" />
    		</tx:attributes>
    	</tx:advice>
    	<aop:config>
    		<!-- 第一个*代表所有的返回值类型;第二个*代表所有的类;第三个*代表类所有方法;..代表子或者孙子包;最后一个..代表所有的参数 -->
    		<aop:pointcut id="switch_session_factory_transactionPointcut" expression="(execution(* sy.service.base..*Impl.*(..)))" />
    		<aop:advisor pointcut-ref="switch_session_factory_transactionPointcut" advice-ref="switch_session_factory_txAdvice" />
    
    
    	</aop:config>
    
    </beans>

    每一个sessionFactory就加一个这个配置:

    <?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:aop="http://www.springframework.org/schema/aop" xmlns:c="http://www.springframework.org/schema/c" xmlns:cache="http://www.springframework.org/schema/cache" xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:lang="http://www.springframework.org/schema/lang" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p" xmlns:task="http://www.springframework.org/schema/task" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
    		http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd
    		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
    		http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
    		http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
    		http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd
    		http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
    		http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd
    		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
    		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
    
    
    <!--自定义表命名  多表映射  admin  -->
    
    	<bean id="s_adminNamingStrategy" class="sy.datasource.sessionFactory.strategy.TNamingStrategy">
        <property name="suffix" value="http://520shuijing.iteye.com/blog/s_admin" />
        </bean>
        <bean id="s_adminSessionFactory" parent="masterSessionFactory">
            <property name="namingStrategy" ref="s_adminNamingStrategy"/>
        </bean>
    
    
    </beans>

    最后在web.xml加上

     <filter>
        <filter-name>openSessionInView</filter-name>
       <!--  <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class> -->
        <filter-class>sy.datasource.sessionFactory.MyOpenSessionInViewFilter</filter-class>
        <init-param>
          <param-name>singleSession</param-name>
          <param-value>true</param-value>
        </init-param>
      </filter>

    到此,spring下的hibernate多表映射就大功造成了!


  • 相关阅读:
    删除 SQL Server 2005 Express 工具
    静态和非静态
    C#中的托管和非托管
    类和结构的区别
    asp.net URL DES加密 什在URL中的使用
    正则替换图片路径
    Oracle 正则 一行转多行
    Oracle 存储过程
    HTTP SOAP Request
    jquery 高亮
  • 原文地址:https://www.cnblogs.com/pekkle/p/6568686.html
Copyright © 2020-2023  润新知