一、缘由

上一篇文章Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法介绍到了怎么样在Sping、MyBatis、Hibernate整合的应用中动态切换DataSource数据源的方法,但最终遗留下一个问题:不能切换数据库方言。数据库方言可能在当前应用的架构中意义不是很大,但是如果单纯用MyBatis或Hibernate做数据库持久化操作,还是要处理这一问题。

 

那么下面将介绍怎么样动态切换SessionFactory,为什么要切换SessionFactory?

因为这里切换SessionFactory就可以实现多数据源和多个SessionFactory,每个SessionFactory有自己独立的数据库配置和SessionFactory的相关配置。我们的数据库方言就配置在SessionFactory这里,所以实现了切换SessionFactory也就实现了切换数据库方言的问题。这个主要是针对Hibernate来操作的,而MyBatis则需要动态切换SqlSessionFactory才行。

 

二、实现代码

1、定义全局切换SessionFactory的工具

package com.hoo.framework.spring.support;

 

/**

 * <b>function:</b> 多数据源

 * @author hoojo

 * @createDate 2013-9-27 上午11:36:57

 * @file CustomerContextHolder.java

 * @package com.hoo.framework.spring.support

 * @project SHMB

 * @blog http://blog.csdn.net/IBM_hoojo

 * @email hoojo_@126.com

 * @version 1.0

 */

public abstract class CustomerContextHolder {

 

    public final static String SESSION_FACTORY_MYSQL = "mysql";

    public final static String SESSION_FACTORY_ORACLE = "oracle";

    

    private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();  

    

    public static void setCustomerType(String customerType) {  

        contextHolder.set(customerType);  

    }  

      

    public static String getCustomerType() {  

        return contextHolder.get();  

    }  

      

    public static void clearCustomerType() {  

        contextHolder.remove();  

    }  

}

同样上面的静态变量和前一文章中介绍的一致,它需要和下面配置文件中的SessionFactory的key对应。

2、实现自己的SessionFactory

定义好接口

package com.hoo.framework.spring.support.core;

 

import org.hibernate.SessionFactory;

 

/**

 * <b>function:</b> 动态SessionFactory接口

 * @author hoojo

 * @createDate 2013-10-12 下午03:29:52

 * @file DynamicSessionFactory.java

 * @package com.hoo.framework.spring.support.core

 * @project SHMB

 * @blog http://blog.csdn.net/IBM_hoojo

 * @email hoojo_@126.com

 * @version 1.0

 */

public interface DynamicSessionFactory extends SessionFactory {

    

    public SessionFactory getHibernateSessionFactory();

}

 

实现接口

package com.hoo.framework.spring.support.core;

 

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.Interceptor;

import org.hibernate.SessionFactory;

import org.hibernate.StatelessSession;

import org.hibernate.TypeHelper;

import org.hibernate.classic.Session;

import org.hibernate.engine.FilterDefinition;

import org.hibernate.metadata.ClassMetadata;

import org.hibernate.metadata.CollectionMetadata;

import org.hibernate.stat.Statistics;

import com.hoo.framework.spring.support.CustomerContextHolder;

 

/**

 * <b>function:</b> 动态数据源实现

 * @author hoojo

 * @createDate 2013-10-12 下午03:31:31

 * @file DynamicSessionFactoryImpl.java

 * @package com.hoo.framework.spring.support.core

 * @project SHMB

 * @blog http://blog.csdn.net/IBM_hoojo

 * @email hoojo_@126.com

 * @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; 

    

    /**

     * @see com.hoo.framework.spring.support.core.DynamicSessionFactory#getHibernateSessionFactory()

     * <b>function:</b> 重写这个方法,这里最关键

     * @author hoojo

     * @createDate 2013-10-18 上午10:45:25

     */

    @Override

    public SessionFactory getHibernateSessionFactory() {

        SessionFactory targetSessionFactory = targetSessionFactorys.get(CustomerContextHolder.getCustomerType());  

        if (targetSessionFactory != null) {  

            return targetSessionFactory;  

        } else if (defaultTargetSessionFactory != null) {  

            return defaultTargetSessionFactory;  

        }  

        return null;

    }

 

 

    @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 Session openSession(Interceptor interceptor) throws HibernateException {

        return this.getHibernateSessionFactory().openSession(interceptor);

    }

 

    @Override

    public Session openSession(Connection connection) {

        return this.getHibernateSessionFactory().openSession(connection);

    }

 

    @Override

    public Session openSession(Connection connection, Interceptor interceptor) {

        return this.getHibernateSessionFactory().openSession(connection, interceptor);

    }

 

    @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;

    }

 

}

上面最重要的就是getHibernateSessionFactory重写这个方法,其他方法和原来实现的无异。重写这个方法后利用CustomerContextHolder动态设置SessionFactory类型就可以动态的切换SessionFactory。

3、动态的事务管理器,因为我们这里是动态切换SessionFactory,所以事务这块也需要动态切换SessionFactory来完成事务的操作。

package com.hoo.framework.spring.support.tx;

 

import javax.sql.DataSource;

import org.hibernate.SessionFactory;

import org.springframework.orm.hibernate3.HibernateTransactionManager;

import org.springframework.orm.hibernate3.SessionFactoryUtils;

import com.hoo.framework.spring.support.core.DynamicSessionFactory;

 

/**

 * <b>function:</b> 重写HibernateTransactionManager事务管理器,实现自己的动态的事务管理器

 * @author hoojo

 * @createDate 2013-10-12 下午03:54:02

 * @file DynamicTransactionManager.java

 * @package com.hoo.framework.spring.support.tx

 * @project SHMB

 * @blog http://blog.csdn.net/IBM_hoojo

 * @email hoojo_@126.com

 * @version 1.0

 */

public class DynamicTransactionManager extends HibernateTransactionManager {

 

    private static final long serialVersionUID = -4655721479296819154L;

    

    /** 

     * @see org.springframework.orm.hibernate4.HibernateTransactionManager#getDataSource()

     * <b>function:</b> 重写

     * @author hoojo

     * @createDate 2013-10-12 下午03:55:24

     */

    @Override

    public DataSource getDataSource() {

        return SessionFactoryUtils.getDataSource(getSessionFactory());

    }

 

    /** 

     * @see org.springframework.orm.hibernate4.HibernateTransactionManager#getSessionFactory()

     * <b>function:</b> 重写

     * @author hoojo

     * @createDate 2013-10-12 下午03:55:24

     */

    @Override

    public SessionFactory getSessionFactory() {

        DynamicSessionFactory dynamicSessionFactory = (DynamicSessionFactory) super.getSessionFactory();  

        SessionFactory hibernateSessionFactory = dynamicSessionFactory.getHibernateSessionFactory();  

        return hibernateSessionFactory;  

    }

}

这里主要重写getDataSource()/getSessionFactory()这两个方法,getSessionFactory方法是利用我们上面定义的接口来动态获取我们在上下文(CustomerContextHolder)中定义切换的SessionFactory对象。而getDataSource则是获得动态SessionFactory的DataSource,这里也不难理解。

4、至此,重写的接口和实现都完成,下面开始配置相关的代码

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

    xmlns:aop="http://www.springframework.org/schema/aop" 

    xmlns:tx="http://www.springframework.org/schema/tx"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://www.springframework.org/schema/beans 

    http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 

    http://www.springframework.org/schema/aop 

    http://www.springframework.org/schema/aop/spring-aop-3.2.xsd 

    http://www.springframework.org/schema/tx  

    http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">

    

    <!-- 配置c3p0数据源 -->

    <bean id="dataSourceOracle" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">

        <property name="driverClass" value="${datasource.driver}"/>

        <property name="jdbcUrl" value="${datasource.url}"/>

        <property name="user" value="${datasource.username}"/>

        <property name="password" value="${datasource.password}"/>

                

        <property name="acquireIncrement" value="${c3p0.acquireIncrement}"/>

        <property name="initialPoolSize" value="${c3p0.initialPoolSize}"/>

        <property name="minPoolSize" value="${c3p0.minPoolSize}"/>

        <property name="maxPoolSize" value="${c3p0.maxPoolSize}"/>

        <property name="maxIdleTime" value="${c3p0.maxIdleTime}"/>

        <property name="idleConnectionTestPeriod" value="${c3p0.idleConnectionTestPeriod}"/>

        <property name="maxStatements" value="${c3p0.maxStatements}"/>

        <property name="numHelperThreads" value="${c3p0.numHelperThreads}"/>

        <property name="preferredTestQuery" value="${c3p0.preferredTestQuery}"/>

        <property name="testConnectionOnCheckout" value="${c3p0.testConnectionOnCheckout}"/>

    </bean>

    

    <bean id="dataSourceMySQL" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">

        <property name="driverClass" value="com.mysql.jdbc.Driver"/>

        <property name="jdbcUrl" value="jdbc:mysql://172.31.108.178:3306/world?useUnicode=true&amp;characterEncoding=UTF-8&amp;zeroDateTimeBehavior=convertToNull"/>

        <property name="user" value="root"/>

        <property name="password" value="jp2011"/>

                

        <property name="acquireIncrement" value="${c3p0.acquireIncrement}"/>

        <property name="initialPoolSize" value="${c3p0.initialPoolSize}"/>

        <property name="minPoolSize" value="${c3p0.minPoolSize}"/>

        <property name="maxPoolSize" value="${c3p0.maxPoolSize}"/>

        <property name="maxIdleTime" value="${c3p0.maxIdleTime}"/>

        <property name="idleConnectionTestPeriod" value="${c3p0.idleConnectionTestPeriod}"/>

        <property name="maxStatements" value="${c3p0.maxStatements}"/>

        <property name="numHelperThreads" value="${c3p0.numHelperThreads}"/>

        <property name="preferredTestQuery" value="${c3p0.preferredTestQuery}"/>

        <property name="testConnectionOnCheckout" value="${c3p0.testConnectionOnCheckout}"/>

    </bean>

    

    <!-- Annotation 配置sessionFactory,配置数据库连接,注入hibernate数据库配置 -->

    <bean id="mySQLSessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">

        <property name="dataSource" ref="dataSourceMySQL"/>

        <property name="packagesToScan" value="com.hoo.**.mysqlentity"/>

        <property name="annotatedClasses">

            <array>

                <value>com.hoo.common.entity.IDGenerator</value>

            </array>

        </property>

        <property name="hibernateProperties">

            <props>

                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>

                <!-- 链接释放策略 on_close | after_transaction | after_statement | auto  -->

                <prop key="hibernate.connection.release_mode">after_transaction</prop>

                <prop key="hibernate.show_sql">true</prop>

                <prop key="hibernate.format_sql">true</prop>

            </props>

        </property>

    </bean>

    

    <!-- Annotation 配置sessionFactory,配置数据库连接,注入hibernate数据库配置 -->

    <bean id="oracleSessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">

        <property name="dataSource" ref="dataSourceOracle"/>

        <property name="packagesToScan" value="com.hoo.**.entity"/>

        <property name="hibernateProperties">

            <props>

                <prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop>

                <prop key="hibernate.connection.release_mode">after_transaction</prop>

                <prop key="hibernate.show_sql">true</prop>

                <prop key="hibernate.format_sql">true</prop>

                <!--prop key="hibernate.hbm2ddl.auto">update</prop-->

            </props>

        </property>

    </bean>

    

    <!-- 动态SessionFactory -->

    <bean id="sessionFactory" class="com.hoo.framework.spring.support.core.DynamicSessionFactoryImpl">

        <property name="defaultTargetSessionFactory" ref="oracleSessionFactory"/>

        <property name="targetSessionFactorys">

            <map>     

                <entry value-ref="oracleSessionFactory" key="oracle"/>

                <entry value-ref="mySQLSessionFactory" key="mysql"/>

            </map> 

        </property>

    </bean>

 

    <!-- 自定义动态切换SessionFactory事务管理器,注入sessionFactory  -->

    <bean id="transactionManager" class="com.hoo.framework.spring.support.tx.DynamicTransactionManager">

        <property name="sessionFactory" ref="sessionFactory" />

    </bean>

    

    <!-- 配置事务的传播特性 -->

    <tx:advice id="txAdvice" transaction-manager="transactionManager">

        <tx:attributes>

            <tx:method name="add*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>

            <tx:method name="edit*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>

            <tx:method name="remove*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>

            <tx:method name="execute*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>

            <tx:method name="*" read-only="true" />

        </tx:attributes>

    </tx:advice>

    

    <!-- 配置那些类、方法纳入到事务的管理 -->

    <aop:config>

        <aop:pointcut expression="execution(* com.hoo.**.service.impl.*.*(..))" id="transactionManagerMethod"/>

        <aop:advisor advice-ref="txAdvice" pointcut-ref="transactionManagerMethod" />

    </aop:config>

</beans>

配置也和我们之前的配置差不多,就是事务管理器部分注入的SessionFactory是我们自己定义的。

5、简单测试

@Test

public void testAdd() {

    // 主要就是这行代码 它才是完成SessionFactory的切换

    CustomerContextHolder.setCustomerType(CustomerContextHolder.SESSION_FACTORY_MYSQL);

    

    DeviceInfo entity = new DeviceInfo();

    entity.setSbbh(System.currentTimeMillis() + "");

    entity.setIpdz("my ip address2");

    entity.setJd(1234);

    try {

        service.add(entity);

    } catch (Exception e) {

        e.printStackTrace();

    }

}

经过测试发现可以查询数据,利用hibernate查询分页也可以生成对应数据库的分页语句。同样在服务层的方法中添加完操作后,特意抛出一个异常,数据也能正常回滚操作,所以DynamicTransactionManager也是起到了该有的作用!

这里我的测试用例是手动切换CustomerContextHolder.setCustomerType的,但实际开发中我们还是得用Spring的Aop中的Interceptor进行切面编程,完成动态切换SessionFactory。上一篇文章Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法已经提到了(读者可以参考该篇博文中的第二节的3、7小节DataSourceMethodInterceptor MultipleDataSourceInterceptor),这里就不再赘述!

 

三、引发的问题

上述的实现如果在使用不当的情况下,在实际开发中很可能存在一些问题!

问题1是这样的,通常事务是在Service这层完成,这个应该是没有异议。倘若是这样的话,问题便出现了。而通常我们在MVC中的视图层中仅仅会调用Service中一个方法来完成所有当前业务的处理。如果这个Service中同时操作dbA、dbB两个数据库,事务提交的时候是用哪个数据库的事务呢?所以我们把不同数据库的操作放在一个方法,就会出现事务的问题的,除非两个数据库的事务能够同时回滚!

大致情景是:Service中的add4Oracle操作Oracle数据库,Service中的add4MySQL操作MySQL数据库,最后把Service中的add4Oracle、add4MySQL方法放到一个operation方法中,MVC视图层的业务控制调用Service中的operation。像这样的情况,如果add4Oracle或add4MySQL方法中的某一个方法出现异常,就需要把两个数据库事务都回滚。

解决办法就是在Service或Dao中的一个方法中同时操作两个数据库,手动完成事务控制。出现异常就全部回滚,没有异常就全部提交,只能这样牺牲下。

问题2是利用拦截器不能同时切换一个方法操作两个数据库的可能,例如一个service中的query方法即需要用query MySQL,也需要query Oracle。那么解决办法就是在query方法中调用当前service的query4Oracle和query4Oracle,那样绕过去还是能利用拦截器进行动态切换的。

四、总结

要完成数据库方言的切换,我们就需要配置多个SessionFactory利用自己实现的DynamicSessionFactory和CustomerContextHolder完成SessionFactory的切换。利用DynamicTransactionManager完成当前Session的事务操作。通过对这些对象的操作和配置,最终可以完成SessionFactory的动态切换。实际使用中虽然有些问题出现,但是最终还是有解决方案,尽管有些不完美。所谓的完美的东西总有它不完美的地方,这样才算完美,比如断臂的维纳斯女神~!

Spring3 整合Hibernate3.5 动态切换SessionFactory (切换数据库方言)的更多相关文章

  1. Spring3 整合MyBatis3 配置多数据源 动态选择SqlSessionFactory

    一.摘要 上两篇文章分别介绍了Spring3.3 整合 Hibernate3.MyBatis3.2 配置多数据源/动态切换数据源 方法 和 Spring3 整合Hibernate3.5 动态切换Ses ...

  2. Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法

    一.开篇 这里整合分别采用了Hibernate和MyBatis两大持久层框架,Hibernate主要完成增删改功能和一些单一的对象查询功能,MyBatis主要负责查询功能.所以在出来数据库方言的时候基 ...

  3. Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源方法

    一.开篇 这里整合分别采用了Hibernate和MyBatis两大持久层框架,Hibernate主要完成增删改功能和一些单一的对象查询功能,MyBatis主要负责查询功能.所以在出来数据库方言的时候基 ...

  4. Spring+Hibernate实现动态SessionFactory切换(改进版)

    前面写了一篇关于动态切换Hibernate SessionFactory的文章 发现存在一些问题: 需要配置多个HibernateTransactionManager和多个Spring 切面 这样带来 ...

  5. 2018-01-08 学习随笔 SpirngBoot整合Mybatis进行主从数据库的动态切换,以及一些数据库层面和分布式事物的解决方案

    先大概介绍一下主从数据库是什么?其实就是两个或N个数据库,一个或几个主负责写(当然也可以读),另一个或几个从只负责读.从数据库要记录主数据库的具体url以及BigLOG(二进制日志文件)的参数.原理就 ...

  6. Spring+Hibernate实现动态SessionFactory切换

    场景: 1)系统有多个数据库 2)且数据库类型也不尽相同 3)现在应用根据某些条件路由到具体的数据库 4)且在spring+hibernate框架下,支持依赖注入 已有实现,spring动态数据源,但 ...

  7. 在SOUI中使用动态多语言切换

    动态语言切换是很多国际化产品的需求,SOUI之前的版本支持静态多语言翻译,通过在程序启动时设置好语言翻译模块,在程序中打开的UI都会自动调用该翻译模块进行文字翻译,但是不支持运行进语言切换. 最近几个 ...

  8. Spring 动态创建并切换数据源

    公司要求后端项目可以进行动态创建并切换数据源,看了网上很多例子大多数使用的都是Spring内置的AbstractRoutingDataSource进行的,使用此方法不是不行但是有诸多缺陷,比如切换时需 ...

  9. SpringBoot与动态多数据源切换

      本文简单的介绍一下基于SpringBoot框架动态多数据源切换的实现,采用主从配置的方式,配置master.slave两个数据库. 一.配置主从数据库 spring: datasource: ty ...

随机推荐

  1. Oracle 的基本使用--基本命令<一>

    sql*plus 的常用命令 连接命令 1.conn[ect] 用法:conn 用户名/密码@网络服务名[as sysdba/sysoper]当用特权用户身份连接时,必须带上 as sysdba 或是 ...

  2. javascript学习第二课

    主要内容: 1.不可变的原始值和可变的对象引用 javascript中的原始值(undefined.null.布尔值.数字和字符串)与对象(包括数组和函数)有着根本的区别.原始值是不可更改的;任何方法 ...

  3. LVM基本概念、管理

    一.传统磁盘管理的问题 当分区大小不够用时无法扩展其大小,只能通过添加磁盘.创建新的分区来扩充空间,但是新添加进来的硬盘是作为独立文件系统存在的,原有的文件系统并未得到扩充,上层应用很多时候只能访问一 ...

  4. POJ1222_EXTENDED LIGHTS OUT

    给出5*6的位置,每个位置有一个灯,一开始每个灯有各自的状态,你可以选定一些位置使得所有与这个位置相邻以及位置本身的灯都取反. 输出合法方案. 本来是找高斯消元找到这个题目的,可是....我发现可以直 ...

  5. JS,数组小练习

    var arr = [4, 0, 7, 9, 0, 0, 2, 6, 0, 3, 1, 0];要求将数组中的0项去掉,将不为0的值存入一个新的数组,生成新的数组 p.p1 { margin: 0.0p ...

  6. p1304 家族

    描述 若某个家族人员过于庞大,要判断两个是否是亲戚,确实还很不容易,现在给出某个亲戚关系图,求任意给出的两个人是否具有亲戚关系. 规定:x和y是亲戚,y和z是亲戚,那么x和z也是亲戚.如果x,y是亲戚 ...

  7. Jade之Code

    Code jade支持内嵌js的代码到jade代码之中. Unbuffered Code 无缓冲代码以-符号开始,无任何额外输出(文本是什么即是什么). jade: - for (var x = 0; ...

  8. replicate-rewrite-db

    replicate-rewrite-db: Tells the slave to translate the default database (that is, the one selected b ...

  9. Java里的构造函数(构造方法)

    构造函数 ,是一种特殊的方法.主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中.特别的一个类可以有多个构造函数 ,可根据其参数个数的不同或参数类型 ...

  10. tomee 第一个 远程调用 Session Bean

    参考文档 http://tomee.apache.org/ http://download.oracle.com/otndocs/jcp/ejb-3.1-pfd-oth-JSpec/ http://d ...