当前位置: 首页>后端>正文

spring4

SpringJDBC使用

Spring框架对JDBC的简单封装。提供了一个JDBCTemplate对象简化JDBC的开发 , 使用非常简单, .

1.2JdbcTemplate开发步骤
①导入spring-jdbc和spring-tx坐标
②创建数据库表和实体
③创建JdbcTemplate对象
④执行数据库操作

  • update():执行DML语句。增、删、改语句
  • queryForMap():查询结果将结果集封装为map集合,将列名作为key,将值作为value 将这条记录封装为一个map集合
    • 注意:这个方法查询的结果集长度只能是1
  • queryForList():查询结果将结果集封装为list集合
    • 注意:将每一条记录封装为一个Map集合,再将Map集合装载到List集合中
  • query():查询结果,将结果封装为JavaBean对象
    • query的参数:RowMapper
      • 一般我们使用BeanPropertyRowMapper实现类。可以完成数据到JavaBean的自动封装
      • new BeanPropertyRowMapper<类型>(类型.class)
  • queryForObject:查询结果,将结果封装为对象
    • 一般用于聚合函数的查询

入门代码

@Test
public void test1(){
        //1. 创建JdbcTemplate对象
        JdbcTemplate jt = new JdbcTemplate(JdbcUtils3.getDataSource());
        //2. 编写sql语句
        String sql = "insert  into `student` values (null ,'马小云',25,'女','北京',100,100)";
        int row = jt.update(sql);
        if(row>0){
                System.out.println("插入成功....");
        }else{
                System.out.println("插入失败....");
        }
}

案例练习

public class JdbcTemplateDemo2 {

    //1. 获取JDBCTemplate对象
    private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
    /**
     * 1. 修改1号数据的 salary 为 10000
     */
    @Test
    public void test1(){

        //2. 定义sql
        String sql = "update emp set salary = 10000 where id = 1001";
        //3. 执行sql
        int count = template.update(sql);
        System.out.println(count);
    }

    /**
     * 2. 添加一条记录
     */
    @Test
    public void test2(){
        String sql = "insert into emp(id,ename,dept_id) values(?,?,?)";
        int count = template.update(sql, 1015, "郭靖", 10);
        System.out.println(count);

    }

    /**
     * 3.删除刚才添加的记录
     */
    @Test
    public void test3(){
        String sql = "delete from emp where id = ?";
        int count = template.update(sql, 1015);
        System.out.println(count);
    }

    /**
     * 4.查询id为1001的记录,将其封装为Map集合
     * 注意:这个方法查询的结果集长度只能是1
     */
    @Test
    public void test4(){
        String sql = "select * from emp where id = or id = ?";
        Map<String, Object> map = template.queryForMap(sql, 1001,1002);
        System.out.println(map);
        //{id=1001, ename=孙悟空, job_id=4, mgr=1004, joindate=2000-12-17, salary=10000.00, bonus=null, dept_id=20}

    }

    /**
     * 5. 查询所有记录,将其封装为List
     */
    @Test
    public void test5(){
        String sql = "select * from emp";
        List<Map<String, Object>> list = template.queryForList(sql);

        for (Map<String, Object> stringObjectMap : list) {
            System.out.println(stringObjectMap);
        }
    }

    /**
     * 6. 查询所有记录,将其封装为Emp对象的List集合
     */

    @Test
    public void test6_2(){
        String sql = "select * from emp";
        List<Emp> list = template.query(sql, new BeanPropertyRowMapper<Emp>(Emp.class));
        for (Emp emp : list) {
            System.out.println(emp);
        }
    }

    /**
     * 7. 查询总记录数
     */

    @Test
    public void test7(){
        String sql = "select count(id) from emp";
        Long total = template.queryForObject(sql, Long.class);
        System.out.println(total);
    }

}           

Spring声明式事物控制

1.事务隔离级别

设置隔离级别,可以解决事务并发产生的问题,如脏读、不可重复读和虚读。
ISOLATION_DEFAULT
ISOLATION_READ_UNCOMMITTED
ISOLATION_READ_COMMITTED
ISOLATION_REPEATABLE_READ
ISOLATION_SERIALIZABLE

2.事务传播行为

REQUIRED:如果当前没有事务, 就新建一个事务, 如果已经存在一个事务中, 加入到这个事务中。一般的选择(默认值)
SUPPORTS:支持当前事务, 如果当前没有事务, 就以非事务方式执行(没有事务)
MANDATORY:使用当前的事务, 如果当前没有事务, 就抛出异常
REQUERS_NEW:新建事务, 如果当前在事务中, 把当前事务挂起。
NOT_SUPPORTED:以非事务方式执行操作, 如果当前存在事务, 就把当前事务挂起
NEVER:以非事务方式运行, 如果当前存在事务, 抛出异常
NESTED:如果当前存在事务, 则在嵌套事务内执行。如果当前没有事务, 则执行R EQUIRED类似的操作
超时时间:默认值是-1,没有超时限制。如果有,以秒为单位进行设置
是否只读:建议查询时设置为只读

声明式事物控制概述

  1. JavaEE体系进行分层开发,事务处理位于业务层,Spring提供了分层设计业务层的事务处理解决方案。

  2. spring框架为我们提供了一组事务控制的接口。具体在后面的第二小节介绍。这组接口是在spring-tx-5.0.2.RELEASE.jar中。

  3. spring的事务控制都是基于AOP的,它既可以使用编程的方式实现,也可以使用配置的方式实现。我们学习的重点是使用配置的方式实现。

事务控制的API介绍

PlatformTransactionManager

此接口是spring的事务管理器,它里面提供了我们常用的操作事务的方法,如下图:

spring4,第1张

我们在开发中都是使用它的实现类

spring4,第2张

常用的实现类:
org.springframework.jdbc.datasource.DataSourceTransactionManager 使用Spring JDBC或iBatis 进行持久化数据时使用
org.springframework.orm.hibernate5.HibernateTransactionManager 使用Hibernate版本进行持久化数据时使用

TransactionDefinition

描述的是事务的定义信息对象,里面有如下方法:


spring4,第3张

事物的隔离级别

spring4,第4张

事物的传播行为

事务的传播行为:它解决的是两个被事务管理的方法互相调用问题。它与数据库没关系,是程序内部维护的问题。

spring4,第5张
REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。一般的选择(默认值)
SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行(没有事务)
MANDATORY:使用当前的事务,如果当前没有事务,就抛出异常 REQUERS_NEW:新建事务,如果当前在事务中,把当前事务挂起。
NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
NEVER:以非事务方式运行,如果当前存在事务,抛出异常 NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行REQUIRED类似的操作。

TransactionStatus

此接口提供的是事务具体的运行状态,方法介绍如下图:


spring4,第6张

转账案例环境准备

创建maven项目

spring4,第7张

导入依赖jar包

<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.38</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>c3p0</groupId>
        <artifactId>c3p0</artifactId>
        <version>0.9.1.2</version>
    </dependency>
    <dependency>
        <groupId>cglib</groupId>
        <artifactId>cglib</artifactId>
        <version>3.2.2</version>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.8.7</version>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.7.0</version>
            <configuration>
                <target>1.8</target>
                <source>1.8</source>
            </configuration>
        </plugin>
    </plugins>
</build>

编写实体类

public class Account {

    private int id ;

    private String username ;

    private double money ;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }
}

编写数据访问层

接口AccountDao

public interface AccountDao {

    /**
     * 根据用户名称查询用户信息
     * @param name
     * @return
     */
    Account findByName(String name) throws SQLException;

    /**
     * 更新账户信息
     * @param source
     */
    void update(Account source) throws SQLException;
}

实现类AccountDaoImpl

@Repository
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {

    @Override
    public Account findByName(String name) throws SQLException {
        String sql = "select * from account where username = ";

        try {
            return getJdbcTemplate().queryForObject(sql, new BeanPropertyRowMapper<Account>(Account.class), name);
        } catch (DataAccessException e) {
            e.printStackTrace();
        }

        return  null ;
    }

    @Override
    public void update(Account account) throws SQLException {
        String sql = "update account set money = where username = ";
        getJdbcTemplate().update(sql,account.getMoney(),account.getUsername());
    }
}

创建业务层

接口AccountService

public interface AccountService {

    /**
     * 转账业务功能
     * @param sourceName  转出账户
     * @param targetName  转入账户
     * @param money         转账金额
     * @throws SQLException
     */
    public void transfer(String sourceName, String targetName, double money) throws SQLException;
}

实现类AccountServiceImpl

public class AccountServiceImpl implements AccountService {

    private AccountDao accountDao ;

    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }

    @Override
    public void transfer(String sourceName, String targetName, double money) throws SQLException {

        //1.根据名称查询转出账户
        Account source = accountDao.findByName(sourceName);
        //2.根据名称查询转入账户
        Account target = accountDao.findByName(targetName);
        //3.转出账户减钱
        source.setMoney(source.getMoney()-money);
        //4.转入账户加钱
        target.setMoney(target.getMoney()+money);
        //5.更新转出账户余额
        accountDao.update(source);
        //int i = 10 / 0 ; //特意添加的异常代码,让程序执行异常
        //6.更新转入账户余额
        accountDao.update(target);
    }
}

编写核心配置文件

编写Spring核心配置文件beans.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: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.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd">

        <!--加载属性文件-->
        <context:property-placeholder location="classpath:db.properties"></context:property-placeholder>

        <!--配置dao-->
        <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl">
            <property name="dataSource" ref="dataSource"></property>
        </bean>
        <!--配置service-->
        <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
            <property name="accountDao" ref="accountDao"></property>
        </bean>

        <!--配置数据源-->
        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <property name="driverClass" value="${jdbc.driver}"></property>
            <property name="jdbcUrl" value="${jdbc.url}"></property>
            <property name="user" value="${jdbc.username}"></property>
            <property name="password" value="${jdbc.password}"></property>
        </bean>

</beans>

编写测试类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:beans.xml")
public class AccountServiceTest {

    @Autowired
    private AccountService accountService ;

    @Test
    public void transfer() throws SQLException {
        //zhangsan给lisi转账1000元
        accountService.transfer("zhangsan","lisi",1000);
    }
}

声明式事务控制实现

配置事务步骤

1. 配置事务管理器
2. 配置事务的通知:此时我们需要导入事务的约束 tx名称空间和约束,同时也需要aop的名称空间和约束
       tx:advice标签配置事务通知:
            属性:
                id:给事务通知起一个唯一标识
                transaction-manager:给事务通知提供一个事务管理器引用
3. 配置AOP中的通用切入点表达式
4. 建立事务通知和切入点表达式的对应关系
5. 配置事务的属性:在事务的通知tx:advice标签的内部

配置声明式事务控制

<?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.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!--加载属性文件-->
    <context:property-placeholder location="classpath:db.properties"></context:property-placeholder>

    <!--配置dao-->
    <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!--配置service-->
    <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"></property>
    </bean>

    <!--配置数据源-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"></property>
        <property name="jdbcUrl" value="${jdbc.url}"></property>
        <property name="user" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>

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

    <!--配置事务通知-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!--配置事务的属性
            isolation:用于指定事务的隔离级别,默认值为DEFAULT,表示使用数据库默认隔离级别
            propagation:用于指定事务的传播行为,默认值为REQUIRED,表示一定会有事务,增删改的选择,
                         查询选择SUPPORTS
            read-only:用于指定事务是否只读,布尔值,只有查询方法才能设为true,默认值为false表示读写
            timeout:用于指定事务的超时时间,默认值为-1表示永不超时,如果指定数值,以秒为单位
            rollback-for:用于指定一个异常,当产生该异常时事务回滚,产生其他异常时事务不回滚。
                          没有默认值,表示产生任何异常都回滚
            no-rollback-for:用于指定一个异常,当产生该异常时事务不回滚,产生其他异常时事务回滚。
                            没有默认值,表示任何异常都回滚
        -->
        <tx:attributes>
            <!--此配置意思为:当以get/find开头的方法支持事务,且该事务为只读-->
            <tx:method name="get*" propagation="REQUIRED" read-only="true"/>
            <tx:method name="find*" propagation="REQUIRED" read-only="true"/>

            <!--此配置意思为:当以update,del,delete,insert,add,save开头的方法进行事务控制,会回滚-->
            <tx:method name="updaet*" propagation="REQUIRED"></tx:method>
            <tx:method name="del*" propagation="REQUIRED"></tx:method>
            <tx:method name="delete*" propagation="REQUIRED"></tx:method>
            <tx:method name="insert*" propagation="REQUIRED"></tx:method>
            <tx:method name="add*" propagation="REQUIRED"></tx:method>
            <tx:method name="save*" propagation="REQUIRED"></tx:method>
        </tx:attributes>
    </tx:advice>

    <!--配置AOP-->
    <aop:config>
        <!--配置切入点,也就是事务控制要在哪一层上,一般事务在业务层控制-->
        <aop:pointcut id="txPointCut" expression="execution(* com.itheima.service.impl.*.*(..))"></aop:pointcut>
        <!--建立切入点表达式和事务通知之间的关系-->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"></aop:advisor>
    </aop:config>

</beans>

Spring注解事务控制

修改数据访问层

spring4,第8张

修改业务层

spring4,第9张

修改配置文件

修改配置文件beans.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: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.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!--加载属性文件-->
    <context:property-placeholder location="classpath:db.properties"></context:property-placeholder>

    <!--开启组件扫描-->
    <context:component-scan base-package="com.itheima"></context:component-scan>

    <!--配置数据源-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"></property>
        <property name="jdbcUrl" value="${jdbc.url}"></property>
        <property name="user" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>

    <!--配置JDBC-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--配置spring基于注解的事务管理器
      1、配置事务管理器
      2、开启spring对注解事务的支持
      3、在需要使用事务的类上使用@Transactional注解
    -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--开启spring对注解事务的支持-->
    <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>

</beans>
spring4,第10张

①使用@Transactional在需要进行事务控制的类或是方法上修饰, 注解可用的属性同xml配置方式, 例如:隔离级别、传播行为等。
②注解使用在类上,那么该类下的所有方法都使用同一套注解参数配置
③使用在方法上,不同的方法可以采用不同的事务参数配置.
④Xml配置文件中要开启事务的注解驱动<tx:annotation-driven/>


https://www.xamrdz.com/backend/3x71925649.html

相关文章: