软件世界网 购物 网址 三丰软件 | 小说 美女秀 图库大全 游戏 笑话 | 下载 开发知识库 新闻 开发 图片素材
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
移动开发 架构设计 编程语言 Web前端 互联网
开发杂谈 系统运维 研发管理 数据库 云计算 Android开发资料
  软件世界网 -> 架构设计 -> Spring+JDBC的简单配置和开发 -> 正文阅读

[架构设计]Spring+JDBC的简单配置和开发


目前很多的公司采用了spring+jdbc的配置开发项目,下面介绍怎么配置环境到开发时候的注意事项:
①引入必要的jar文件
JDBC驱动(mysql为例):
mysql-connector-5.1.7.jar
数据库连接池(dbcp为例):
commons-dbcp.jar
commons-pool.jar
spring核心必须包:
spring.jar
commons-logging.jar
AOP非必须(方便使用建议添加):
cglib-nodep-2.1_3.jar
aspectjrt.jar
注解(一般都会使用):
common-annotations.jar
aspectjweaver.jar
[img]http://img.blog.csdn.net/20160329143618791
一、配置数据源dataSource:
学过了spring后,这里采用spring容器管理来实例化数据源,一般在配置之前都会开启事务管理的命名空间,一般都会使用事务管理。
在配置一个工程的时候一定要注意的是循序渐进,不要一口气全部配置好所有的东西,这样如果经验不丰富的朋友,可能难以解决现有的报错。所以在配置好数据源的时候测试一下这个数据源是否正确,如果经验比较丰富的可以多配置几步再测试。
<?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">

        <!-- 开启注解 -->
        <context:annotation-config/>

        <!-- 配置数据连接池 -->
        <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
            <property name="url" value="jdbc:mysql:///test?useUnicode=true&amp;characterEncoding=UTF-8"></property>
            <property name="driverClassName" value="org.gjt.mm.mysql.Driver"></property>
            <property name="username" value="root"></property>
            <property name="password" value="heyingxxx"></property>

            <!-- 连接池初始值 -->
            <property name="initialSize" value="2"/>
            <!-- 连接池最大值 -->
            <property name="maxActive" value="100"/>
            <!-- 连接池最大空闲值 -->
            <property name="maxIdle" value="5"/>
            <!-- 连接池最小空闲值 -->
            <property name="minIdle" value="2"/>
        </bean>
</beans>

这个dataSource已经交给spring容器管理了,现在使用spring实例化这个bean,以前介绍过方法:
public void testSave() throws Exception {
        try {
            AbstractApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
//          PersonService personService = (PersonService) context.getBean("personService");
            DataSource dataSource = (DataSource) context.getBean("dataSource");
//          personService.save(new Person("heying", 2));
            System.out.println(dataSource.getConnection());
            context.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

[img]http://img.blog.csdn.net/20160329144748853
二、配置业务bean,这边模拟一个员工的录入,简化操作,user只有两个属性,id和name
Person.java:
package com.heying.bean;

public class Person {
    private String name;
    private Integer id;

    // 初始化person
    public Person(String name, Integer id) {
        this.name = name;
        this.id = id;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
}

PersonService接口:
package com.heying.service;

import java.util.List;

import com.heying.bean.Person;
public interface PersonService {
    public void save(Person person);
    public void update(Integer id,Person person);
    public List<Person> findAll();
}

PersonService接口的实现类:
业务层面需要调用到数据库,所以需要将dataSource注入到PersonServiceBean,在dataSource无法直接实现数据的增删改查,如果这里只是单单的把数据库注入到PersonServiceBean显得有些不足,需要通过getConnection等大量的重复动作, 所以在JdbcTemplate中有很多现有的方法,这样就需要在使用PersonServiceBean的时候不仅需要注入dataSource,还需要初始化JdbcTemplate,这边可以使用两个或者多个方式。第一种是前面介绍的在业务bean->PersonServiceBean初始化时候注入dataSource时候采用setter方式,在setter中new JdbcTemplate(dataSource),还有一种就是在实例化业务bean->PersonServiceBean的时候使用init方法,值得注意的是,一定在注入了dataSource之后初始化JdbcTemplate,否则dataSource为null将报错,因为JdbcTemplate需要数据源初始化。这边采用init初始化:
package com.heying.service.impl;

import java.util.List;
import javax.annotation.Resource;
import javax.sql.DataSource;

import com.heying.bean.Person;
import com.heying.service.PersonService;

    public class PersonServiceBean implements PersonService{
        @Resource
        private DataSource dataSource; //注入dataSource到PersonServiceBean
        private JdbcTemplate jdbcTemplate ; // 可以使用init方法初始化,也可以在bean.xml中配置使用setter方法注入PersonServiceBean时候初始化

        public void init(){
        jdbcTemplate = new JdbcTemplate(dataSource);
        }

        @Override
        public void save(Person person) {
            try {
                System.out.println(dataSource.getConnection());
                System.out.println(jdbcTemplate);
                jdbcTemplate.update("insert into t_user (name,id) values (?,?) ", 
                    new Object[]{person.getName(),person.getId()},
                    new int[]{Types.VARCHAR,Types.INTEGER});
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public void update(Integer id, Person person) {

        }

        @Override
        public List<Person> findAll() {
            return null;
        }
}

bean.xml文件:
<bean id="personService" class="com.heying.service.impl.PersonServiceBean" init-method="init"></bean>

测试:
@Test
    public void testSave() throws Exception {
        try {
            AbstractApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
            PersonService personService = (PersonService) context.getBean("personService");
            personService.save(new Person("heying51123", 1102));
            context.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

结果:
[img]http://img.blog.csdn.net/20160329151038837
数据库:
[img]http://img.blog.csdn.net/20160329151220605
基于注解的事务管理器:
这样就能完成了一个完整的过程,但是在企业开发中还必须使用事务管理,所以,还必须配置事务管理,防止异常发生时同一个事务中所有的操作回滚,这里注意的是在spring中的事务管理,默认只回滚RuntimeException()的异常,这类异常不能通过捕获处理,所以就不需要捕获的异常是特殊的Exception的子类(unchecked Exception),而其他的异常也是Exception的子类,这些属于检查异常,默认是不回滚事务的,所以需要在回滚的方法上定义   @Transactional(rollbackFor=Exception.class):

bean.xml文件:
事务管理的命名空间已经引入,要想使事务交给spring管理,需要和注解一样需要注册事务管理器,初始化时就需要将dataSource注入到txManager,交给事务管理器管理
        <!-- 注册事务管理器 -->
        <tx:annotation-driven transaction-manager="txManager"/>

        <!-- 配置事务管理器 -->
        <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"></property>
        </bean>

第一次使用insert插入重复主键看看数据库是否回滚:
save方法:
    @Override
    public void save(Person person) throws Exception{
        try {
            System.out.println(dataSource.getConnection());
            System.out.println(jdbcTemplate);
            int updateRows = jdbcTemplate.update("insert into t_user (name,id) values (?,?) ", 
                    new Object[]{person.getName(),person.getId()},
                    new int[]{Types.VARCHAR,Types.INTEGER});
            int updateRows2 = jdbcTemplate.update("insert into t_user (name,id) values (?,?) ", 
                    new Object[]{person.getName(),person.getId()},
                    new int[]{Types.VARCHAR,Types.INTEGER});
            System.out.println("insert影响了: "+updateRows+ " ROWS");
        } catch (Exception e) {
            throw new Exception("普通捕获异常");
        }
    }

测试:
    public class TestCase {
    private static AbstractApplicationContext context;
    private static PersonService personService;

    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
        context = new ClassPathXmlApplicationContext("bean.xml");
        personService = (PersonService) context.getBean("personService");
    }

    @Test
    public void testSave() throws Exception {
        try {
            personService.save(new Person("heying110", 1102));
        } catch (Exception e) {
            System.err.println("********异常********* "+e.getMessage()); 
        }finally{
            List<Person> list = personService.findAll();
            for (int i = 0; i < list.size(); i++) {
                System.out.println("##-->> "+list.get(i).getName());
                System.out.println("##-->> "+list.get(i).getId());
            }
            context.close();
        }
    }
}

结果:
[img]http://img.blog.csdn.net/20160330105553172
总结: 显然第二条数据检查异常并没有影响第一条数据的插入
第二次加上@Transactional(rollbackFor=Exception.class)定义需要回滚的异常:
    @Transactional(rollbackFor=Exception.class)
    public void save(Person person) {
        fun()...
    }

测试:
personService.save(new Person("heying110", 1103));

结果:
[img]http://img.blog.csdn.net/20160330105728906
1103没有插入,第二条记录出现异常,第一条就回滚了,一般数据库访问出现的异常比较基层,一般不可能通过try语句快解决的,这样也有的喜欢抛出一个运行期异常,不用指明@Transactional(rollbackFor=Exception.class)也能回滚所有出现异常的操作。
不是所有的访问都需要事务的,比如查询操作可以不适用事务管理,使用事务管理,必定会影响性能,所以介绍几种常见的事务传播属性(Propagation )的方式:
REQUIRES(默认):加入当前正要执行的事务不在另外一个事务里,那么就起一个新的事务
PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行,跟随调用的方法是否有事务决定。
PROPAGATION_MANDATORY:要求在一个已有的事务中执行,业务方法不能发起自己的事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW:不管业务没有没有事务,总会开启新事务,如果调用方法中存在事务,把当前事务挂起,新的事务会创建,直到方法结束后,新事务才算结束,原先挂起的事务恢复执行。
PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果被另外一个方法调用,且当前存在事务,就把当前事务挂起,调用方法结束后,原先事务在继续执行。
PROPAGATION_NEVER:要求在一个没有事务方式中执行,如果存在事务,则抛出异常,和MANDATORY相反。
NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中,如果没有活动的事务,则按照REQUIRES属性执行,它使用一个单独的事务,这个事务拥有多个回滚保存点,内部事务不会对外部事务产生影响,它只对DataSourceTransactionManager事务管理起效。
Spring事务隔离级别:
1. ISOLATION_DEFAULT: 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.
另外四个与JDBC的隔离级别相对应
2. ISOLATION_READ_UNCOMMITTED(读未提交): 这是事务最低的隔离级别,它充许令外一个事务可以看到这个事务未提交的数据,这种隔离级别会产生脏读,不可重复读和幻像读。
3. ISOLATION_READ_COMMITTED:(读已提交) 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据
4. ISOLATION_REPEATABLE_READ(可重复读): 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读 ,它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生。
5. ISOLATION_SERIALIZABLE:(串行化) 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行, 除了防止脏读,不可重复读外,还避免了幻像读。
mysql数据隔离级别藏参考:

http://xm-king.iteye.com/blog/770721

介绍一下基于XML方式的事务管理,采用了AOP中的通知管理将事务交给spring管理
        <aop:config>
            <!-- 定义一个切面,拦截的包以及子包类任意类任意方法 -->
            <aop:pointcut id="transactionPointcut" expression="execution(* com.heying.service.PersonService..*.*(..))"/>
            <aop:advisor advice-ref="txtAdvice" pointcut-ref="transactionPointcut"/>
        </aop:config>
        <tx:advice id="txtAdvice" transaction-manager="transactionManager">
            <tx:attributes>
                <tx:method name="get*" read-only="true" propagation="NOT_SUPPORTED"/> <!-- get开头方法不使用 -->
                <tx:method name="*"/><!-- 其他方法,默认 propagation="REQUIRED" -->                
            </tx:attributes>
        </tx:advice>

......显示全文...
    点击查看全文


上一篇文章      下一篇文章      查看所有文章
2016-04-01 16:50:07  
架构设计 最新文章
Opengl教程之读取obj并绘制在picturecontro
读《企业应用架构模式》第五章并发
StepbyStepintoSpring(IOC)
设计模式(2)用例图之一
使用实体组件系统(ECS)开发”吃方块”游戏实
编程学习之简单工厂模式与策略模式
Invalidprojectdescription.
基于Redis实现分布式消息队列(2)
《开源框架那点事儿15》:借船下海还是造船
原型模式——浅复制和深复制
360图书馆 软件开发资料 文字转语音 购物精选 软件下载 美食菜谱 新闻资讯 电影视频 小游戏 Chinese Culture 股票 租车
生肖星座 三丰软件 视频 开发 短信 中国文化 网文精选 搜图网 美图 阅读网 多播 租车 短信 看图 日历 万年历 2018年1日历
2018-1-16 17:36:06
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  软件世界网 --