Spring框架整理第三发,JdbcTemplate的使用和声明式事务。
JdbcTemplate
简介:JdbcTemplate是Spring框架提供的操作数据库的工具类,功能和DBUtils类似
JdbcTemplate使用方法:
导包:
数据库连接:
c3p0-0.9.1.2.jar
mysql
-connector-java-5.1.7-bin.jar
|
核心包:
spring-beans-4.0.0.RELEASE.jar
spring-context-4.0.0.RELEASE.jar
spring-core-4.0.0.RELEASE.jar
spring-expression-4.0.0.RELEASE.jar
|
依赖包:
commons-logging-1.1.3.jar
|
aop和aop增强包
com.springsource.net.sf.cglib-2.2.0.jar
com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
spring-
aop
-4.0.0.RELEASE.jar
spring-aspects-4.0.0.RELEASE.jar
|
jdbc和事务所需的包:
spring-
jdbc
-4.0.0.RELEASE.jar
spring-
orm
-4.0.0.RELEASE.jar
spring-
tx
-4.0.0.RELEASE.jar
|
config_jdbc.properties配置文件
user=root
password=123456
jdbcUrl=jdbc:mysql://127.0.0.1:3306/jdbc_template
driverClass=com.mysql.jdbc.Driver
配置c3p0数据库连接池
①引入外部配置文件
<context:property-placeholder location="classpath:config_jdbc.properties"/>
②配置数据库连接的具体信息
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="${user}"></property>
<property name="password" value="${password}"></property>
<property name="jdbcUrl" value="${jdbcUrl}"></property>
<property name="driverClass" value="${driverClass}"></property>
</bean>
配置JdbcTemplate
<!-- 使用Spring提供的JdbcTemplate操作数据库 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!-- 告诉它用哪个数据源 -->
<constructor-arg name="dataSource" ref="dataSource"></constructor-arg>
</bean>
想要使用具名参数还需要配置配置NamedParameterJdbcTemplate
<!-- 要使用具名参数还需要配置一个额外的类NamedParameterJdbcTemplate -->
<bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
<!-- 装配数据源 -->
<constructor-arg name="dataSource" ref="dataSource"></constructor-arg>
</bean>
Jdbc测试练习:
测试
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import com.atguigu.bean.Employee;
public class TxTest {
ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
JdbcTemplate jdbcTemplate = ioc.getBean(JdbcTemplate.class);
NamedParameterJdbcTemplate njt = ioc.getBean(NamedParameterJdbcTemplate.class);
/**
* 实验1:测试数据源
* @throws SQLException
*/
@Test
public void testDataSource() throws SQLException {
DataSource bean = ioc.getBean(DataSource.class);
System.out.println(bean.getConnection());
}
/**
* 实验2:更新一条数据
*/
@Test
public void testUpdate() {
String sql = "update employee set salary = ? where emp_id= ?";
int update = jdbcTemplate.update(sql, 10000, 3);
System.out.println(update);
}
/**
* 实验3:批量插入
*/
@Test
public void testBatch() {
String sql = "insert into employee(emp_name, salary)values(? , ?)";
List<Object[]> list = new ArrayList<>();
list.add(new Object[]{"张三", 1800});
list.add(new Object[]{"赵武", 1300});
list.add(new Object[]{"二娜", 1100});
list.add(new Object[]{"王麻子", 1100});
list.add(new Object[]{"赵四", 1900});
jdbcTemplate.batchUpdate(sql, list);
}
/**
* 实验4:查询emp_id=5的数据库记录,封装为一个Java对象返回
*/
@Test
public void test1() {
String sql = "select emp_id,emp_name,salary from employee where emp_id = ?";
//使用无参构造器不行
//注意后边要写BeanPropertyRowMapper(Class<T> mappedClass)
RowMapper<Employee> rowMapper = new BeanPropertyRowMapper<>(Employee.class);
Employee object = jdbcTemplate.queryForObject(sql, rowMapper, 5);
System.out.println(object);
}
/**
* 实验5:查询salary>4000的数据库记录,封装为List集合返回
*/
@Test
public void test2() {
String sql = "select emp_id,emp_name,salary from employee where salary > ?";
RowMapper<Employee> rowMapper = new BeanPropertyRowMapper<>(Employee.class);
List<Employee> query = jdbcTemplate.query(sql, rowMapper, 4000);
System.out.println(query);
}
/**
* 实验6:查询最大salary
*/
@Test
public void test3() {
String sql = "select max(salary) from employee";
Double object = jdbcTemplate.queryForObject(sql, Double.class);
System.out.println(object);
}
/**
* 实验7:使用带有具名参数的SQL语句插入一条员工记录,并以Map形式传入参数值
*/
@Test
public void test4() {
String sql = "insert into employee (emp_id,emp_name,salary) values(:emp_id, :emp_name, :salary)";
//创建一个map集合分别给emp_id, emp_name,salary
Map<String, Object> map = new HashMap<>();
map.put("emp_id", null);
map.put("emp_name", "张三");
map.put("salary", 123.2);
//不用将map包装也可以
//System.out.println(map);
//MapSqlParameterSource source = new MapSqlParameterSource(map);
njt.update(sql, map);
}
//实验8:重复实验7,以SqlParameterSource形式传入参数值
@Test
public void test5() {
String sql = "insert into employee (emp_id,emp_name,salary) values(:emp_id, :emp_name, :salary)";
Employee emp = new Employee(null, "赵六", 1234.3);
//同样是给具名参数赋值
BeanPropertySqlParameterSource bpsps = new BeanPropertySqlParameterSource(emp);
njt.update(sql, bpsps);
}
}
声明式事务
事务概述
在JavaEE企业级开发的应用领域,为了保证数据的完整性和一致性,必须引入数据库事务的概念,所以事务管理是企业级应用程序开发中必不可少的技术。
事务就是一组由于逻辑上紧密关联而合并成一个整体(工作单元)的多个数据库操作,这些操作要么都执行,要么都不执行。
事务的关键属性(ACID)
原子性(atomicity):“原子”的本意是“不可再分”,事务的原子性表现为一个事务中涉及到的多个操作在逻辑上缺一不可。事务的原子性要求事务中的所有操作要么都执行,要么都不执行。
一致性(consistency):“一致”指的是数据的一致,具体是指:所有数据都处于满足业务规则的一致性状态。一致性原则要求:一个事务中不管涉及到多少个操作,都必须保证事务执行之前数据是正
确的,事务执行之后数据仍然是正确的。如果一个事务在执行的过程中,其中某一个或某几个操作失败了,则必须将其他所有操作撤销,将数据恢复到事务执行之前的状态,这就是回滚。
隔离性(isolation):在应用程序实际运行过程中,事务往往是并发执行的,所以很有可能有许多事务同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏。隔离性原则要求多个事务在并发执行过程中不会互相干扰。
持久性(durability):持久性原则要求事务执行完成后,对数据的修改永久的保存下来,不会因各种系统错误或其他意外情况而受到影响。通常情况下,事务对数据的修改应该被写入到持久化存储器中。
如何使用Spring框架配置事务?
方式①:通过注解
方式②:通过xml文件配置
Spring声明式事务的属性
isolation 指定事务的隔离级别
no-rollback-for 指定那些异常不回滚
rollback-for 指定那些异常回滚
read-only 指定方法是只读的,可以提高效率,默认是false
timeout 设置方法在指定的时间内没有执行完成就进行回滚。 单位:s
propagation 定义事务的传播属性
|
事务的传播属性:
无论使用什么方式配置声明式事务,都可以配置以上事务属性
基于注解的事务配置:
①
导包(如上)
② 在需要添加事务的方法上加上@Transactional
注解
③Spring的配置文件中配置事务管理器
<!-- 添加事务管理器组件DataSourceTransactionManager -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 使用set方法注入数据源 -->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 开启基于注解声明式事务
注意配置transaction-manager属性,它引用了我们事务管理组件对象,这里要和事务管理器组件id一致
默认是transactionManager
-->
<tx:annotation-driven transaction-manager="transactionManager"/>
基于XML的事务配置:
①导包
②在Spring的配置文件中进行配置
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 装配数据源 -->
<constructor-arg name="dataSource" ref="dataSource"></constructor-arg>
</bean>
<!--使用xml配置事务方法 -->
<aop:config>
<!-- 设置添加事务的方法,使用切入点表达式-->
<aop:pointcut expression="execution(* *.checkout(..))" id="mypoint"/>
<!-- 将事务方法和事务的相关配置关联起来 -->
<aop:advisor advice-ref="myAdvice" pointcut-ref="mypoint" />
</aop:config>
<!-- tx配置事务的属性 (使用tx名称空间)-->
<tx:advice id="myAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- 配置事务的属性,多个事务方法也可以在这个里面放,name设置事务方法名,propagation设置事务相关信息 -->
<tx:method name="checkout" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>