Spring2学习笔记(2)-使用数据库

1 使用数据库

1.1 配置数据源

1.1.1 JNDI 数据源

  < bean id = "dataSource"

      class = "org.springframework.jndi.JndiObjectFactoryBean" scope = "singleton" >

    < property name = "jndiName" value = "/jdbc/RantzDatasource" />

    < property name = "resourceRef" value = "true" />

  </ bean >

resourceRef :当为 true 的时候, jndiName 会被添加 java:comp/env/

Spring2.0 里使用 jee 命名空间里的配置

  < jee:jndi-lookup id = "dataSource"

    jndi-name = "/jdbc/RantzDatasource"

    resource-ref = "true" />    

 

1.1.2   基于 JDBC 驱动的数据源

  < bean id = "dataSource"

      class = "org.springframework.jdbc.datasource.DriverManagerDataSource" >

< property name = "driverClassName"

value = " oracle.jdbc.driver.OracleDriver " />

< property name = "url"

value = " jdbc:oracle:thin:@192.168.1.1:1521:test " />

    < property name = "username" value = "zrl" />

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

  </ bean >

1.1.3   使用数据源连接池

类似 JDBC 驱动,使用 org.apache.commons.dbcp.BasicDataSource 类驱动

 

1.2    使用 JDBC

1.2.1   使用 JDBC 模板

编写基于 JDBC DAO 涉及配置 JDBC 模板 Bean 、把它装配到 DAO 类、然后使用这个模板访问数据库,这个过程要配置 3 Bean :一个数据源、一个模板、一个 DAO

JdbcTemplate :最基本的 JDBC 模板,利用 JDBC 和简单的索引参数对数据库的简单访问

NamedParameterJdbcTemplate :能够在执行查询时把值绑定到 SQL 里的命名参数,而不是使用索引参数

SimpleJdbcTemplate :选用 java5 的特性,来简化 JDBC 模板的使用

 

1.2.1.1             JdbcTemplate

1)        XML 配置

  < bean id = "jdbcTemplate"

    class = "org.springframework.jdbc.core.JdbcTemplate" >

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

  </ bean >

2)        JdbcTemplate 装配到 DAO

public class JdbcRantDao implements RantDao {

...

   private JdbcTemplate jdbcTemplate ;

   public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {

       this . jdbcTemplate =jdbcTemplate;

   }

}

3)        设置 JdbcRantDao jdbcTemplate 属性

  < bean id = "rantDao" class = "com.roadrantz.dao.jdbc.JdbcRantDao" >

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

  </ bean >

 

4)        使用保存

   private static final String MOTORIST_INSERT = "insert into motorist (id, email, password, firstName, lastName) "

                     + "values (null, ?,?,?,?)" ;

   public void saveMotorist(Motorist motorist) {

      jdbcTemplate .update(

                        MOTORIST_INSERT ,

                        new Object[] { motorist.getEmail(),

                              motorist.getPassword(), motorist.getFirstName(),

                               motorist.getLastName() });

   }

5)        使用查询

   private static final String MOTORIST_SELECT = "select id, email, password, firstName, lastName from motorist" ;

   private static final String MOTORIST_BY_ID_SELECT = MOTORIST_SELECT

                     + " where id=?" ;

   public Motorist getMotoristById ( long id) {

      List matches = jdbcTemplate .query( MOTORIST_BY_ID_SELECT ,

                        new Object[] { Long.valueOf (id) }, new RowMapper() {

                           public Object mapRow(ResultSet rs, int rowNum)

                                              throws SQLException,

                                             DataAccessException {

                              Motorist motorist = new Motorist();

 

                              motorist.setId(rs.getInt(1));

                               motorist.setEmail(rs.getString(2));

                              motorist.setPassword(rs.getString(3));

                              motorist.setFirstName(rs.getString(4));

                              motorist.setLastName(rs.getString(5));

                               return motorist;

                           }

                        });

 

      return matches.size() > 0 ? (Motorist) matches.get(0) : null ;

   }

 

1.2.1.2             NamedParameterJdbcTemplate

使用方法及步骤同 jdbcTemplate

命名参数:

   private static final String MOTORIST_INSERT = "insert into motorist (id, email, password, firstName, lastName) "

                     + "values (null, :email, :password, :firstName, :lastName)" ;

使用保存

   public void saveMotorist (Motorist motorist) {

      Map<String, String> parameters = new HashMap<String, String>();

      parameters.put( "email" , motorist.getEmail());

      parameters.put( "password" , motorist.getPassword());

      parameters.put( "firstName" , motorist.getFirstName());

      parameters.put( "lastName" , motorist.getLastName());

      jdbcTemplate .update( MOTORIST_INSERT , parameters);

   }

 

1.2.1.3             SimpleJdbcTemplate

使用方法及步骤同 jdbcTemplate

查询

   public Motorist getMotoristById ( long id) {

      List<Motorist> matches = jdbcTemplate .query(

                        MOTORIST_BY_ID_SELECT ,

                        new ParameterizedRowMapper<Motorist>() {

                            public Motorist mapRow(ResultSet rs, int rowNum)

                                             throws SQLException {

                              Motorist motorist = new Motorist();

 

                              motorist.setId(rs.getInt(1));

                               motorist.setEmail(rs.getString(2));

                              motorist.setPassword(rs.getString(3));

                              motorist.setFirstName(rs.getString(4));

                              motorist.setLastName(rs.getString(5));

                              return motorist;

                           }

                        }, id);

 

      return matches.size() > 0 ? matches.get(0) : null ;

   }

 

1.2.2   使用 Spring JDBC DAO 支持类

DAO 类继承 JdbcDaoSupport

public class JdbcRantDao extends JdbcDaoSupport implements RantDao

只需配置 jdbcTemplate dataSource

  < bean id = "rantDao" class = "com.roadrantz.dao.jdbc.JdbcRantDao" >

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

  </ bean >

  < bean id = "rantDao" class = "com.roadrantz.dao.jdbc.JdbcRantDao" >

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

  </ bean >

使用 getJdbcTemplate().update

 

NamedParameterJdbcDaoSupport SimpleJdbcDaoSupport 的使用方法类似

 

1.3    Spring 里集成 Hibernate

1.3.1   使用 Hibernate 模板

1)        配置 HibernateTemplate

  < bean id = "hibernateTemplate"

      class = "org .springframework .orm .hibernate3.HibernateTemplate" >

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

  </ bean >

2)        配置 sessionFactory

使用典型的 Hibernate 映射文件

   < bean id = "sessionFactory"

         class = "org .springframework .orm .hibernate3.LocalSessionFactoryBean" >

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

      < property name = "mappingResources" >

         < list >

            < value > com /roadrantz /domain/Rant.hbm .xml </ value >

            < value > com /roadrantz /domain/Motorist.hbm .xml </ value >

            < value > com /roadrantz /domain/Vehicle.hbm .xml </ value >

         </ list >

      </ property >

      < property name = "hibernateProperties" >

         < props >

            < prop key = "hibernate .dialect" > ${hibernate .dialect} </ prop >

         </ props >

      </ property >

   </ bean >  

Java5 也可以使用被注解的域对象(这里不做说明)

3)        通过 Hibernate 模板访问数据

public class HibernateRantDao implements RantDao {

...

   private Hibernate Template hibernate Template;

   public void setTemplate( Hibernate Template template) {

       this .hibernate Template =template;

   }

}

4)        Spring 里配置 DAO

  < bean id = "rantDao" class = "com.roadrantz.dao.hibernate.HibernateRantDao" >

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

  </ bean >

 

5)        使用

  public Vehicle findVehicleByPlate(String state, String plateNumber) {

      List results = getHibernateTemplate()

                        .find( "from " + VEHICLE + " where state = ? and plateNumber = ?" ,

                                          new Object[] { state, plateNumber });

 

      if (results.size() > 0) {

         return (Vehicle) results.get(0);

      }

 

      return null ;

   }

 

   public Motorist getDriverById (Integer id) {

      return (Motorist) getHibernateTemplate().load(Motorist. class , id);

   }

 

 

1.3.2   建立基于 Hibernate DAO

1)        继承 HibernateDaoSupport

public class HibernateRantDao extends HibernateDaoSupport implements RantDao

 

2)        数据访问方法使用 getHibernateTemplate()

 

3)        修改 spring 配置的 Dao

< bean id = "rantDao" class = "com.roadrantz.dao.hibernate.HibernateRantDao" >

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

  </ bean >

 

1.3.3   使用 Hibernate3 上下文会话

HibernateTemplate 的缺点是具有一定的侵入性。使用上下文把 DAO 实现与 Spring 解耦,缺点是它们抛出 Hibernate 特有的异常

1)        定义 session

public class HibernateContextualSessionsRantDao implements RantDao {

...

   private SessionFactory sessionFactory ;

   public void setSessionFactory(SessionFactory sessionFactory) {

      this . sessionFactory = sessionFactory;

   }

}

2)        Spring 里配置的 DAO 同上

3)        访问

   public void saveRant (Rant rant) {

      sessionFactory .getCurrentSession() .saveOrUpdate(rant);

   }

 

1.4    缓存

Spring Modules 会提供一个代理来拦截方法并把结果保存到缓存,它并没有提供一个实际的缓存解决方案,而是要依赖于第三方的缓存方案。这里选择 EHCache

1.4.1   配置缓存方案

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

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

       xmlns:ehcache = "http://www.springmodules.org/schema/ehcache"

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

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

            http://www.springmodules.org/schema/ehcache

            http://www.springmodules.org/schema/cache/springmodules-ehcache.xsd" >

 

  < ehcache:config

     configLocation = "classpath:ehcache.xml" />

     

  < ehcache:annotations >

    < ehcache:caching id = "rantzCacheModel" cacheName = "rantzCache" />

  </ ehcache:annotations >  

</ beans >

 

EHCache.xml 文件内容

< ehcache >

  < defaultCache

      maxElementsInMemory = "500"

      eternal = "true"

      overflowToDisk = "false"

      memoryStoreEvictionPolicy = "LFU" />

  < cache name = "rantzCache"

      maxElementsInMemory = "500"

      eternal = "true"

      overflowToDisk = "false"

      memoryStoreEvictionPolicy = "LFU" />

</ ehcache >

<defaultCache> 是必须有的, <cache> 定义了另一个缓存

memoryStoreEvictionPolicy 当达到最大时的驱逐策略:最近使用 (LRU) 、先入先出 (FIFO) 、较入使用 (LFU)

1.4.2   缓存的代理 Bean

  < ehcache:proxy id = "rantDao"

      refId = "rantDaoTarget" >

    < ehcache:caching

        methodName = "getRantsForDay"

        cacheName = "rantzCache" />

    < echache:flushing

    methodName = "saveRant"

        cacheName = "rantzCache"

        when = "before" />

  </ ehcache:proxy >

< ehcache:caching> 元素声明哪个方法要被拦截、其返回要保存到哪个缓存

< echache:flushing> 元素声明了会清空缓存的方法

1.4.3   注解驱动的缓存

@Cacheable :声明一个方法的返回值应该被缓存

@CacheFlush :声明一个方法是清空缓存的触发器

  @CacheFlush (modelId= "rantzCacheModel" )

  public void saveRant(Rant rant);

 

  @Cacheable (modelId= "rantzCacheModel" )

  public List<Rant> getAllRants();

 

xml 中配置

  < ehcache:annotations >

    < ehcache:caching id = "rantzCacheModel" cacheName = "rantzCache" />

    < ehcache:caching id = "rantzFlushModel" cacheName = "rantzCache" when = "before" />

  </ ehcache:annotations >

 

 

 

1.5    事务管理

ACID :原子性( Atomic )、一致性( Consistent )、隔离性( Isolated )、持久性( Durable

1.5.1   事务管理器

1.5.1.1             JDBC 事务

  < bean id = "transactionManager"

class = "org.springframework.jdbc.datasource.DataSourceTransactionManager " >

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

  </ bean >

 

1.5.1.2             Hibernate 事务

  < bean id = "transactionManager"

      class = "org.springframework.orm.hibernate3.HibernateTransactionManager " >

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

  </ bean >

 

1.5.2   Spring 中编写事物

      

 

1.5.3   声明式事务

public class RantServiceImpl implements RantService {

   public void addRant(Rant rant) {

      rant.setPostedDate( new Date());

      Vehicle rantVehicle = rant.getVehicle();

      Vehicle existingVehicle = rantDao .findVehicleByPlate(rantVehicle

                        .getState(), rantVehicle.getPlateNumber());

      if (existingVehicle != null ) {

         rant.setVehicle(existingVehicle);

      } else {

         rantDao .saveVehicle(rantVehicle);

      }

      rantDao .saveRant(rant);

   }

}

1.5.3.1             代理事务

  < bean id = "rantService"    class = "org.springframework.transaction.interceptor.TransactionProxyFactoryBean" >

    < property name = "target" ref = "rantServiceTarget" />   // 装配事务目标

    < property name = "proxyInterfaces" value = "com.roadrantz.service.RantService" />        // 指定代理接口

    < property name = "transactionManager" ref = "transactionManager" /> // 装配事务管理器

    < property name = "transactionAttributes" >      // 装配事务规则、边界

      < props >

        < prop key = "add*" > PROPAGATION_REQUIRED </ prop >

        < prop key = "*" > PROPAGATION_SUPPORTS,readOnly </ prop >

      </ props >

    </ property >

  </ bean >

 

PROPAGATION_REQUIRED: 表示此方法必须在一个事务中运行

PROPAGATION_SUPPORTS :表示当前方法不需要事务性上下文。

 

1.5.3.2             创建一个事务代理模板

Bean

  < bean id = "txProxyTemplate"    class = "org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract=”true” >

    < property name = "transactionManager" ref = "transactionManager" /> // 装配事务管理器

    < property name = "transactionAttributes" >      // 装配事务规则、边界

      < props >

        < prop key = "add*" > PROPAGATION_REQUIRED </ prop >

        < prop key = "*" > PROPAGATION_SUPPORTS,readOnly </ prop >

      </ props >

    </ property >

  </ bean >

Bean

< bean id = "rantService" parent="txProxyTemplate" >

< property name = "target" ref = "rantServiceTarget" />  

< property name = "proxyInterfaces" value = "com.roadrantz.service.RantService" />

</ bean >

 

1.5.3.3             Spring2.0 里声明事务

增加 tx 名称空间

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

       xsi:schemaLocation = "...

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

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

配置通知

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

    < tx:attributes >

       < tx:method name = "add*" propagation = "REQUIRED" />

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

    </ tx:attributes >

  </ tx:advice >

通知器

  < aop:config >

< aop:advisor advice-ref = "txAdvice"

pointcut = "execution(* *..RantService.*(..))" />

  </ aop:config >

表示通知 RantService 接口的所有方法

 

1.5.3.4             注释驱动事务

@Transactional (propagation = Propagation. SUPPORTS , readOnly = true )

public interface RantService {

  @Transactional (propagation = Propagation. REQUIRED )

  public void addRant(Rant rant);

  ...

}

只需在 XML 上加上以下配置代码

< tx:annotation-driven transaction-manager = "transactionManager" />

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值