zoukankan      html  css  js  c++  java
  • Spring持久化

    1. Spring的DAO理念

    Spring提供了一套抽象的DAO类,供开发者扩展,这有利于以统一的方式操作各种DAO技术,如JDO、JDBC等,这些抽象DAO类提供了设置数据源及相关辅助信息的方法,而其中的一些方法同具体DAO技术相关。目前,SpringDAO抽象提供了以下几种类。

    • JdbcDaoSupport:JDBC DAO抽象类,开发者需要为它设置数据源(DataSource),通过子类,开发者能够获得JdbcTemplate来访问数据库。
    • HibernateDaoSupport:Hibernate DAO抽象类。开发者需要为它配置Hibernate SessionFactory。通过其子类,开发者能够获得Hibernate的实现。
    • JdoDaoSupport:Spring为JDO提供了DAO抽象类,开发者需要为它配置PersistenceManagerFactory,通过其子类开发者能够获得JdoTemplate。

    在使用Spring的DAO框架进行数据库存取时,无须接触使用特定的数据库技术,通过一个数据存取接口来操作即可。

    例1.1 在Spring中利用DAO模式向tb_user表中添加数据。

    (1)定义一个实体类对象User,然后在类中定义对应的数据库表字段的属性。关键代码如下:

    package com.cn.aop;
    
    public class User {
        private Integer id;
        private String name;
        private Integer age;
        private String sex;
        public Integer getId() {
            return id;
        }
        public void setId(Integer id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public Integer getAge() {
            return age;
        }
        public void setAge(Integer age) {
            this.age = age;
        }
        public String getSex() {
            return sex;
        }
        public void setSex(String sex) {
            this.sex = sex;
        }
    }

    (2)创建接口UserDAOImpl,并定义用来执行数据添加的insertUser()方法。其中insertUser()方法中使用的参数是User实体对象。代码如下:

    package com.cn.aop;
    
    public interface UserDAOImpl {
        public void insertUser(User user);   //添加用户信息的方法
    }

    (3)编写实现这个DAO接口的UserDAO类,并在该类中实现接口中定义的方法。首先定义一个用于操作数据库的数据源对象DataSource,通过它创建一个数据库连接对象建立与数据库的连接,这个数据源对象在Spring中提供了javax.sql.DataSource接口的实现,只需要在Spring的配置文件中进行相关的配置即可,稍后会有关于Spring的配置文件。这个类中实现了接口的抽象方法insertUser()方法,通过这个方法访问数据库,关键代码如下:

    package com.cn.aop;
    
    import java.sql.Connection;
    import java.sql.SQLException;
    
    import javax.sql.DataSource;
    
    import java.sql.PreparedStatement;
    
    public class UserDAO implements UserDAOImpl {
        private DataSource dataSource;
        public DataSource getDataSource() {
            return dataSource;
        }
        public void setDataSource(DataSource dataSource) {
            this.dataSource = dataSource;
        }
        //向数据表tb_user中添加数据
        @Override
        public void insertUser(User user) {
            String name = user.getName();
            Integer age = user.getAge();
            String sex = user.getSex();
            Connection conn = null;
            PreparedStatement ps = null;
            try {
                //获取数据库连接
                conn = dataSource.getConnection();
                //添加数据的SQL语句
                String sql = "insert into tb_user(name,age,sex) values(?,?,?)";
                ps = conn.prepareStatement(sql);
                ps.setString(1, name);
                ps.setInt(2, age);
                ps.setString(3, sex);
                //执行SQL语句
                ps.executeUpdate();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }finally{
                try {
                    ps.close();
                    conn.close();
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                
            }
    
        }
    
    }

    (4)编写Spring的配置文件applicationContext.xml,在这个配置文件中首先定义一个JavaBean名称为DataSource的数据源,它是Spring中的DriverManagerDataSource类的实例。然后再配置前面编写完userDAO类,并且注入它的DataSource属性值。具体配置代码如下:

    <?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:p="http://www.springframework.org/schema/p"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
        
        <!-- 配置数据源 -->
        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName">
                <value>com.mysql.jdbc.Driver</value>
            </property>
            <property name="url">
                <value>jdbc:mysql://localhost:3306/test</value>
            </property>
            <property name="username">
                <value>root</value>
            </property>
            <property name="password">
                <value>1234</value>
            </property>
        </bean>
        <!-- 为UserDAO注入数据源 -->
        <bean id="userDAO" class="com.cn.aop.UserDAO">
            <property name="dataSource">
                <ref local="dataSource"/>
            </property>
        </bean>
    </beans>

    (5)创建类Manager,在其main()方法中的关键代码如下:

    package com.cn.aop;
    
    import org.springframework.beans.factory.BeanFactory;
    import org.springframework.beans.factory.xml.XmlBeanFactory;
    import org.springframework.core.io.ClassPathResource;
    import org.springframework.core.io.Resource;
    
    public class Manger {
        public static void main(String[] args){
            //装载配置文件
            Resource resource = new ClassPathResource("applicationContext.xml");
            BeanFactory factory = new XmlBeanFactory(resource);
            //实例化User对象
            User user = new User();
            user.setName("张三");
            user.setAge(new Integer(30));
            user.setSex("男");
            //获取UserDAO
            UserDAO userDAO = (UserDAO) factory.getBean("userDAO");
            //执行添加方法
            userDAO.insertUser(user);
            System.out.println("数据添加成功!");
        }
    }

    程序运行后,数据表tb_user添加的数据如下图所示:

    2. 事务应用的管理

     事务的管理通常分为两种方式,即编程式事务管理和声明式事务管理,在Spring中这两种事务管理方式都非常优秀。

    • 编程式事务管理

      在Spring中主要有两种编程式事务的实现方法,分别使用PlatformTransactionManager接口的事务管理器或TransactionTemplate实现。虽然两者各有优缺点,但是推荐使用TransactionTemplate实现方式,因为它符合Spring的模板模式。

    说明:TransactionTemplate模板和Spring的其他模板一样,它封装了资源的打开和关闭等常用的重复代码,在编写程序的时候只需要完成需要的业务代码即可。

     例2.1 利用TransactionTemplate实现Spring编程式事务管理。

    (1)首先要在Spring的配置文件中声明事务管理器和TransactionTemplate并为TransactionExample配置相关信息,关键代码如下:

    <?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:p="http://www.springframework.org/schema/p"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
        
        <!-- 配置数据源 -->
        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName">
                <value>com.mysql.jdbc.Driver</value>
            </property>
            <property name="url">
                <value>jdbc:mysql://localhost:3306/test</value>
            </property>
            <property name="username">
                <value>root</value>
            </property>
            <property name="password">
                <value>1234</value>
            </property>
        </bean>
        
        <!-- 定义TransactionTemplate模板 -->
        <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
            <property name="transactionManager">
                <ref bean="transactionManager"/>
            </property>
            <property name="propagationBehaviorName">
                <value>PROPAGATION_REQUIRED</value>
            </property>
        </bean>
        <!-- 定义事务管理器 -->
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource">
                <ref bean="dataSource"></ref>
            </property>
        </bean>
            <!-- 为TransactionExample注入数据源 -->
        <bean id="transactionExample" class="com.cn.aop.TransactionExample">
            <property name="dataSource">
                <ref local="dataSource"/>
            </property>
            <property name="transactionManager">
                <ref local="transactionManager"/>
            </property>
            <property name="transactionTemplate">
                <ref local="transactionTemplate"/>
            </property>
        </bean>
    </beans>

    (2)创建类TransactionExample,定义数据添加的方法,在方法中执行两次数据库添加的操作,并用事务对操作进行保护。关键代码如下:

    package com.cn.aop;
    
    import java.sql.Connection;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    import javax.sql.DataSource;
    
    import org.springframework.jdbc.datasource.DataSourceUtils;
    import org.springframework.transaction.PlatformTransactionManager;
    import org.springframework.transaction.TransactionStatus;
    import org.springframework.transaction.support.TransactionCallback;
    import org.springframework.transaction.support.TransactionTemplate;
    
    public class TransactionExample {
        DataSource dataSource;   //注入数据源
        PlatformTransactionManager transactionManager;  //注入事务管理器
        TransactionTemplate transactionTemplate;   //注入TransactionTemplate模板
        public DataSource getDataSource() {
            return dataSource;
        }
        public void setDataSource(DataSource dataSource) {
            this.dataSource = dataSource;
        }
        public PlatformTransactionManager getTransactionManager() {
            return transactionManager;
        }
        public void setTransactionManager(PlatformTransactionManager transactionManager) {
            this.transactionManager = transactionManager;
        }
        public TransactionTemplate getTransactionTemplate() {
            return transactionTemplate;
        }
        public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
            this.transactionTemplate = transactionTemplate;
        }
        
        public void transactionOperation() {
            transactionTemplate.execute(new TransactionCallback() {
                @Override
                public Object doInTransaction(TransactionStatus status) {
                    Connection conn = DataSourceUtils.getConnection(dataSource); //获得数据库连接
                    try {
                        Statement stmt = conn.createStatement();
                        //执行两次添加方法
                        stmt.execute("insert into tb_user(name,age,sex) values('小强','26','男')");
                        stmt.execute("insert into tb_user(name,age,sex) values('小红','22','女')");
                        System.out.println("操作执行成功!");
                    } catch (SQLException e) {
                        transactionManager.rollback(status);
                        System.out.println("操作执行失败,事务回滚!");
                        System.out.println("原因:"+e.getMessage());
                    }
                    return null;
                }
                
            });
        }
    }

    (3)创建类Manger,在其main()方法中的代码如下:

    package com.cn.aop;
    
    import org.springframework.beans.factory.BeanFactory;
    import org.springframework.beans.factory.xml.XmlBeanFactory;
    import org.springframework.core.io.ClassPathResource;
    import org.springframework.core.io.Resource;
    
    public class Manger2 {
    
        public static void main(String[] args) {
            //装载配置文件
            Resource resource = new ClassPathResource("applicationContext.xml");
            BeanFactory factory = new XmlBeanFactory(resource);
            //获取TransactionExample
            TransactionExample transactionExample = (TransactionExample) factory.getBean("transactionExample");
            //执行添加方法
            transactionExample.transactionOperation();
        }
    
    }

    (4)为了测试事务是否配置正确,在transactionOperation()方法中执行两次添加操作的语句之间添加两句代码,制造人为异常。也就是说,当第一条操作语句执行成功后,第二天语句因为程序的异常无法执行成功,这种情况下如果事务成功回滚说明事务配置成功,添加的代码如下:

    int a=0;
    a=8/a;

    程序执行后控制台会输出相关信息。

    • 声明式事务管理

      Spring的声明式事务不涉及组建依赖关系,它通过AOP实现事务管理,Spring本身就是一个容器,相对EJB容器而言,Spring显得更为轻便小巧。在使用Spring的声明式事务时无须编写任何代码,便可通过实现基于容器的事务管理。Spring提供了一些可供选择的辅助类,这些辅助类简化了传统的数据库操作流程,在一定程度上节省了工作量,提高了编程效率,所以推荐使用声明式事务。

    在Spring中常用TransactionProxyFactoryBean完成声明式事务管理。

    例2.2 利用TransactionProxyFactoryBean实现Spring声明式事务管理。

    (1)首先在配置文件中定义数据源DataSource和事务管理器,这个事务管理器被注入到TransactionProxyFactoryBean中,设置代理对象和事务属性。这里的目标对象是以内部类的方式定义的。配置文件中的关键代码如下:

    <?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:p="http://www.springframework.org/schema/p"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
        <!-- 配置数据源 -->
        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName">
                <value>com.mysql.jdbc.Driver</value>
            </property>
            <property name="url">
                <value>jdbc:mysql://localhost:3306/test</value>
            </property>
            <property name="username">
                <value>root</value>
            </property>
            <property name="password">
                <value>1234</value>
            </property>
        </bean>
        <!-- 定义事务管理器 -->
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource">
                <ref bean="dataSource"></ref>
            </property>
        </bean>
        <!-- 定义TransactionProxy -->
        <bean id="transactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
            <property name="transactionManager">
                <ref local="transactionManager"/>
            </property>
            <property name="target">
                <bean id="addDAO" class="com.cn.dao.AddDAO">
                    <property name="dataSource">
                        <ref local="dataSource"/>
                    </property>
                </bean>
            </property>
            <property name="proxyTargetClass" value="true"/>
            <property name="transactionAttributes">
                <props>
                    <prop key="add*">PROPAGATION_REQUIRED</prop>
                </props>
            </property>
        </bean>
    </beans>

    (2)其次编写操作数据库的AddDAO类,该类中的addUser()方法是关键,在该方法中执行了两次数据的插入操作,其在配置TransactionProxyFactoryBean时被定义为事务性方法,并指定了事务属性,所以方法中的所有数据库操作都被当作一个事务处理。类中的代码如下:

    package com.cn.dao;
    
    import org.springframework.jdbc.core.support.JdbcDaoSupport;
    
    import com.cn.aop.User;
    
    public class AddDAO extends JdbcDaoSupport {
        //添加用户方法
        public void addUser(User user) {
            //执行添加的SQL语句
            String sql = "insert into tb_user(name,age,sex) values('"+
                    user.getName()+"','"+user.getAge()+"','"+user.getSex()+"')";
            //执行两次添加方法
            getJdbcTemplate().execute(sql);
            getJdbcTemplate().execute(sql);
        }
    }

    (3)创建类Manger,在其main()方法中的代码如下:

    package com.cn.dao;
    
    import org.springframework.beans.factory.BeanFactory;
    import org.springframework.beans.factory.xml.XmlBeanFactory;
    import org.springframework.core.io.ClassPathResource;
    import org.springframework.core.io.Resource;
    
    import com.cn.aop.AddDAO;
    import com.cn.aop.User;
    
    public class Manger {
    
        public static void main(String[] args) {
            //装载配置文件
            Resource resource = new ClassPathResource("applicationContext.xml");
            BeanFactory factory = new XmlBeanFactory(resource);
            //获得AddDAO
            AddDAO addDAO = (AddDAO) factory.getBean("transactionProxy");
            //实例化User对象
            User user = new User();
            user.setName("张三");
            user.setAge(new Integer(30));
            user.setSex("男");
            //执行数据库添加方法
            addDAO.addUser(user);
        }
    
    }
  • 相关阅读:
    SQL Sever语言 存储过程及触发器
    计蒜客 挑战难题 移除数组中的重复元素
    projecteuler Sum square difference
    码农谷 求前N项之和
    projecteuler Smallest multiple
    计蒜客 挑战难题 寻找插入位置
    Largest palindrome product
    计蒜客 挑战难题 元素移除
    码农谷 球从M米高度自由下落第N次落地时反弹的高度
    挑战难题 奇怪的国家
  • 原文地址:https://www.cnblogs.com/gaopeng527/p/4477642.html
Copyright © 2011-2022 走看看