Spring3 Annotation + Hibernate3-jpa2.0 + CGLIB + 多数据源(动态数据源)
来源:互联网 发布:英语单词读法软件 编辑:程序博客网 时间:2024/05/22 11:45
一、定义一个测试用Entity。
二、applicationContext.xml与META-INF/persistent.xml
三、在Spring 2.0.1中引入了AbstractRoutingDataSource, 该类充当了DataSource的路由中介, 能有在运行时, 根据某种key值来动态切换到真正的DataSource上, 同时对于不支持事务隔离级别的JTA事务来说, Spring还提供了另外一个类IsolationLevelDataSourceRouter来处理。IsolationLevelDataSourceRouter: 会根据当前Spring受管事务启用的隔离级别来选定合适的DataSource数据源。
四、数据访问Dao
五、测试
六、关于Spring-AOP: JDK代理和CGLIB代理
1、如果目标对象实现了接口,默认会采用JDK的动态代理机制实现AOP
2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP
3、如果目标对象没有实现接口,必须使用CGLIB生成代理,spring会自动在CGLIB和JDK动态代理之间切换
4、如何强制使用CGLIB生成代理?
(1)添加CGLIB库,SPRING_HOME/lib/cglib/*.jar
(2)在spring的配置文件中加入:<aop:aspectj-autoproxy proxy-target-class="true"/>
5、JDK代理和CGLIB代理的区别?
(1)JDK代理只能对实现了接口的类生成代理,而不能针对类
(2)CGLIB是针对类实现代理的,主要对指定的类生成一个子类,并覆盖其中的方法,因为是继承,所以不能使用final来修饰类或方法
七、关于IsolationLevelDataSourceRouter
public class IsolationLevelDataSourceRouterextends AbstractRoutingDataSourceDataSource that routes to one of various target DataSources based on the current transaction isolation level. The target DataSources need to be configured with the isolation level name as key, as defined on the TransactionDefinition interface.
This is particularly useful in combination with JTA transaction management (typically through Spring's JtaTransactionManager). Standard JTA does not support transaction-specific isolation levels. Some JTA providers support isolation levels as a vendor-specific extension (e.g. WebLogic), which is the preferred way of addressing this. As alternative (e.g. on WebSphere), the target database can be represented through multiple JNDI DataSources, each configured with a different isolation level (for the entire DataSource). The present DataSource router allows to transparently switch to the appropriate DataSource based on the current transaction's isolation level.
The configuration can for example look like this, assuming that the target DataSources are defined as individual Spring beans with names "myRepeatableReadDataSource", "mySerializableDataSource" and "myDefaultDataSource":
Alternatively, the keyed values can also be data source names, to be resolved through a DataSourceLookup: by default, JNDI names for a standard JNDI lookup. This allows for a single concise definition without the need for separate DataSource bean definitions.
Note: If you are using this router in combination with Spring's JtaTransactionManager, don't forget to switch the "allowCustomIsolationLevels" flag to "true". (By default, JtaTransactionManager will only accept a default isolation level because of the lack of isolation level support in standard JTA itself.)
- @Entity
- public class Person implements Serializable {
- private static final long serialVersionUID = 1L;
- @Id @GeneratedValue @Column(name = "id")
- private Integer id;
- @Column(name = "last_name")
- private String lastName;
- @Column(name = "first_name")
- private String firstName;
- public String getFirstName(){return firstName;}
- public void setFirstName(String firstName){this.firstName = firstName;}
- public String getLastName(){return lastName;}
- public void setLastName(String lastName){this.lastName = lastName; }
- public Integer getId(){return id;}
- public void setId(Integer id){this.id = id;}
- }
二、applicationContext.xml与META-INF/persistent.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:tx="http://www.springframework.org/schema/tx"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
- http://www.springframework.org/schema/tx
- http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-3.0.xsd
- http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
- <!--指定spring容器自动扫描的包:@Repository...-->
- <context:component-scan base-package="com.logcd.test,com.logcd.dao,com.logcd.service"/>
- <!--使用CGLIB代理-->
- <aop:aspectj-autoproxy proxy-target-class="true"/>
- <bean
- class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
- <bean id="ds1"
- class="org.springframework.jdbc.datasource.DriverManagerDataSource">
- <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
- <property name="url" value="jdbc:mysql://localhost:3306/springapp"/>
- <property name="username" value="root"/>
- <property name="password" value="root"/>
- </bean>
- <bean id="ds2"
- class="org.springframework.jdbc.datasource.DriverManagerDataSource">
- <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
- <property name="url" value="jdbc:mysql://localhost:3306/test"/>
- <property name="username" value="root"/>
- <property name="password" value="root"/>
- </bean>
- <!--动态选择数据源-->
- <bean id="dataSource" class="com.logcd.util.DynamicDataSource">
- <property name="targetDataSources">
- <map key-type="java.lang.String">
- <entry key="1" value-ref="ds1"/>
- <entry key="2" value-ref="ds2"/>
- </map>
- </property>
- <property name="defaultTargetDataSource" ref="ds1"/>
- </bean>
- <bean id="entityManagerFactory"
- class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
- destroy-method="destroy">
- <property name="dataSource" ref="dataSource" />
- <property name="jpaVendorAdapter">
- <bean
- class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
- <property name="database" value="MYSQL"/>
- <property name="generateDdl" value="true"/>
- <property name="showSql" value="true"/>
- </bean>
- </property>
- </bean>
- <bean id="transactionManager"
- class="org.springframework.orm.jpa.JpaTransactionManager">
- <property name="dataSource" ref="dataSource"/>
- <property name="entityManagerFactory"
- ref="entityManagerFactory"/>
- </bean>
- <tx:annotation-driven transaction-manager="transactionManager"/>
- </beans>
- <persistence xmlns="http://java.sun.com/xml/ns/persistence"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/persistencehttp://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
- version="1.0">
- <!-- local or global(JTA) transaction -->
- <persistence-unit name="SpringJpa" transaction-type="RESOURCE_LOCAL"/>
- </persistence>
三、在Spring 2.0.1中引入了AbstractRoutingDataSource, 该类充当了DataSource的路由中介, 能有在运行时, 根据某种key值来动态切换到真正的DataSource上, 同时对于不支持事务隔离级别的JTA事务来说, Spring还提供了另外一个类IsolationLevelDataSourceRouter来处理。IsolationLevelDataSourceRouter: 会根据当前Spring受管事务启用的隔离级别来选定合适的DataSource数据源。
- import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
- public class DynamicDataSource extends AbstractRoutingDataSource {
- @Override
- protected Object determineCurrentLookupKey() {
- return DbContextHolder.getDbType();
- }
- }
- public class DbContextHolder {
- private static final ThreadLocal<Object> contextHolder = new ThreadLocal<Object>();
- public static void setDbType(Object dbType) {
- contextHolder.set(dbType);
- }
- public static String getDbType() {
- return (String) contextHolder.get();
- }
- public static void clearDbType() {
- contextHolder.remove();
- }
- }
四、数据访问Dao
- import java.io.Serializable;
- import java.util.List;
- import javax.persistence.EntityManager;
- import javax.persistence.PersistenceContext;
- import javax.persistence.Query;
- import org.springframework.stereotype.Repository;
- import org.springframework.transaction.annotation.Transactional;
- @Repository
- @Transactional
- public class BaseDao<T>{
- @PersistenceContext
- protected EntityManager em;
- public void persist(T t) {
- em.persist(t);
- }
- @Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
- public T save(T t) {
- return em.merge(t);
- }
- public void delete(T t) {
- em.remove(t);
- }
- @Transactional(readOnly = true, isolation=Isolation.READ_COMMITTED)
- public T find(Class<T> clazz, Serializable id) {
- return em.getReference(clazz, id);
- }
- @SuppressWarnings("unchecked")
- public List<T> find(String jpql) {
- return em.createQuery(jpql).getResultList();
- }
- @SuppressWarnings("unchecked")
- public List<T> find(String jpql, Object param) {
- return em.createQuery(jpql).setParameter(1, param).getResultList();
- }
- @SuppressWarnings("unchecked")
- public List<T> find(String jpql, Object[] param) {
- Query query = em.createQuery(jpql);
- for (int i = 1; i <= param.length; i++) {
- query.setParameter(i, param[i - 1]);
- }
- return query.getResultList();
- }
- public int findTotalCount(String jpql) {
- return ((Long) em.createQuery(jpql).getSingleResult()).intValue();
- }
- }
五、测试
- import static org.junit.Assert.assertEquals;
- import static org.junit.Assert.assertNotNull;
- import java.util.List;
- import org.junit.Ignore;
- import org.junit.Test;
- import org.junit.runner.RunWith;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.test.context.ContextConfiguration;
- import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
- import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
- import com.logcd.dao.BaseDao;
- import com.logcd.entity.Person;
- import com.logcd.util.DbContextHolder;
- @RunWith(SpringJUnit4ClassRunner.class)
- @ContextConfiguration("classpath:applicationContext.xml")
- public class TestBaseDao extends AbstractJUnit4SpringContextTests{
- @Autowired
- private BaseDao<Person> baseDao;
- @Test
- public void findPersonById(){
- List<Person> persons =
- baseDao.find("from Person a where a.id = ?", new Integer(1));
- assertNotNull(persons);
- assertEquals(persons.size(), 1);
- for(Person person: persons){
- System.out.println(person.getLastName()+" "+person.getFirstName());
- }
- }
- @Test
- public void savePerson(){
- DbContextHolder.setDbType("2");
- Person person = new Person();
- person.setFirstName("Bella");
- person.setLastName("Edward");
- person = baseDao.save(person);
- System.out.println(person.getId());
- DbContextHolder.clearDbType();
- }
- @Ignore
- public void deletePerson(){
- baseDao.delete(baseDao.find(Person.class, new Integer(7)));
- }
- }
六、关于Spring-AOP: JDK代理和CGLIB代理
1、如果目标对象实现了接口,默认会采用JDK的动态代理机制实现AOP
2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP
3、如果目标对象没有实现接口,必须使用CGLIB生成代理,spring会自动在CGLIB和JDK动态代理之间切换
4、如何强制使用CGLIB生成代理?
(1)添加CGLIB库,SPRING_HOME/lib/cglib/*.jar
(2)在spring的配置文件中加入:<aop:aspectj-autoproxy proxy-target-class="true"/>
5、JDK代理和CGLIB代理的区别?
(1)JDK代理只能对实现了接口的类生成代理,而不能针对类
(2)CGLIB是针对类实现代理的,主要对指定的类生成一个子类,并覆盖其中的方法,因为是继承,所以不能使用final来修饰类或方法
七、关于IsolationLevelDataSourceRouter
public class IsolationLevelDataSourceRouterextends AbstractRoutingDataSourceDataSource that routes to one of various target DataSources based on the current transaction isolation level. The target DataSources need to be configured with the isolation level name as key, as defined on the TransactionDefinition interface.
This is particularly useful in combination with JTA transaction management (typically through Spring's JtaTransactionManager). Standard JTA does not support transaction-specific isolation levels. Some JTA providers support isolation levels as a vendor-specific extension (e.g. WebLogic), which is the preferred way of addressing this. As alternative (e.g. on WebSphere), the target database can be represented through multiple JNDI DataSources, each configured with a different isolation level (for the entire DataSource). The present DataSource router allows to transparently switch to the appropriate DataSource based on the current transaction's isolation level.
The configuration can for example look like this, assuming that the target DataSources are defined as individual Spring beans with names "myRepeatableReadDataSource", "mySerializableDataSource" and "myDefaultDataSource":
- <bean id="dataSourceRouter" class="org.springframework.jdbc.datasource.lookup.IsolationLevelDataSourceRouter">
- <property name="targetDataSources">
- <map>
- <entry key="ISOLATION_REPEATABLE_READ" value-ref="myRepeatableReadDataSource"/>
- <entry key="ISOLATION_SERIALIZABLE" value-ref="mySerializableDataSource"/>
- </map>
- </property>
- <property name="defaultTargetDataSource" ref="myDefaultDataSource"/>
- </bean>
- <bean id="dataSourceRouter" class="org.springframework.jdbc.datasource.lookup.IsolationLevelDataSourceRouter">
- <property name="targetDataSources">
- <map>
- <entry key="ISOLATION_REPEATABLE_READ" value="java:comp/env/jdbc/myrrds"/>
- <entry key="ISOLATION_SERIALIZABLE" value="java:comp/env/jdbc/myserds"/>
- </map>
- </property>
- <property name="defaultTargetDataSource" value="java:comp/env/jdbc/mydefds"/>
- </bean>
- <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
- <property name="allowCustomIsolationLevels" value="true"/>
- </bean>
- Spring3 Annotation + Hibernate3-jpa2.0 + CGLIB + 多数据源(动态数据源)
- Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法
- Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法
- Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法
- Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法
- Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法
- Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法
- Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法
- Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法
- Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法
- Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法
- Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法
- Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法
- Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法
- 动态切换数据源(spring3.0+hibernate3.0)
- spring3.0事务的多数据源的annotation-driven用法
- spring3.0事务的多数据源的annotation-driven用法
- spring3.0事务的多数据源的annotation-driven用法
- android ndk增加对stl的支持
- 纯Javascript实现Windows 8 Metro风格实现
- 2013电商新趋势-数据剖析
- eclipse下导入jdk源码
- InsertSort java 实现
- Spring3 Annotation + Hibernate3-jpa2.0 + CGLIB + 多数据源(动态数据源)
- cocos2d-x教程2 精灵
- Android 神模拟器genymotion安装
- [MySQL] 字符集和排序方式
- LU分解版本2_选主元、非原地存储
- linuxmint/ubuntu 修改主机名hostname
- CICS&DB2连接
- 网页截图工具WebThumb
- java应用jquery uploadify 3.2 丢失session