spring提供JDBC
导包

测试JDBC连接
@Test
public void func1() throws IOException {
DataSource dateSource = DruidUtils.getDruidDateSource();
JdbcTemplate jdbcTemplate = new JdbcTemplate(dateSource);
String sql= "INSERT INTO demo VALUES(null,?)";
jdbcTemplate.update(sql,"林伟祥");
}
注入DruidDataSource
在src文件下书写properties
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.password=*******
jdbc.username=root
jdbc.jdbcUrl=jdbc:mysql://localhost:3306/spring?useUnicode=true&characterEncoding=utf8
jdbc.initialSize=5
jdbc.minIdle=5
jdbc.maxActive=20
xml配置
注入阿里的DruidDataSource连接池dataSource,并且将其作为JdbcTemplate属性
<!--load properties-->
<context:property-placeholder location="DruidUtils.properties"/>
<bean class="com.alibaba.druid.pool.DruidDataSource" name="dataSource" destroy-method="close">
<property name="url" value="${jdbc.jdbcUrl}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
JDBC常用API
与Dbutils类似,Dbutils的QueryRunner类似于SpringJDBC的JdbcTemplate,学习如何使用SpringJDBC,根据下列常用API
- execute方法:可以用于执行任何sql语句,一般用于执行DDL语句
- update方法/batchUpdate方法:update方法用于执行新增、修改 、删除等语句;batchUpdate方法用于执行批处理相关语句
- query方法及queryForXXX方法:用于执行查询相关语句
- call方法:用于执行存储过程、函数相关语句
增
// 获取JDBCTemplate
JdbcTemplate jt = new JdbcTemplate(dataSource);
// 增加条目
jt.update("INSERT INTO demo VALUES (NULL ,'Pulsatilla')");
/*
* 批量增加条目
* 最后一个参数是 Object[] 的 List 类型:因为修改一条记录需要一个 Object 数组,
* 修改多条记录就需要一个 List 来存放多个数组
*/
List<Object[]> list = new ArrayList<>();
list.add(new Object[]{10,"张三"});
list.add(new Object[]{11,"李四"});
list.add(new Object[]{12,"王五"});
list.add(new Object[]{13,"赵柳"});
list.add(new Object[]{14,"孙八"});
jt.batchUpdate("INSERT INTO demo VALUES (?,?)",list);
删
// 删除条目
jt.update("DELETE FROM demo WHERE id=1");
改
// 修改条目
jt.update("UPDATE demo SET 'name'='霞洛' WHERE id=5");
查询
/*
查询条目
从数据库中获取一条记录,实际得到对应的一个对象
注意:不是调用 queryForObject(String sql, Class<Employee> requiredType, Object... args) 方法!
而需要调用 queryForObject(String sql, RowMapper<Employee> rowMapper, Object... args)
1、其中的 RowMapper 指定如何去映射结果集的行,常用的实现类为 BeanPropertyRowMapper
2、使用 SQL中的列的别名完成列名和类的属性名的映射,例如 last_name lastName
3、不支持级联属性。 JdbcTemplate 只能作为一个 JDBC 的小工具, 而不是 ORM 框架
*/
// 查询单个条目
User user = jt.queryForObject("SELECT * FROM demo WHERE id=?", new BeanPropertyRowMapper<>(User.class), 1);
// 查询多个条目(注意不是调用的queryForList)
List<User> query = jt.query("SELECT * FROM demo", new BeanPropertyRowMapper<>(User.class));
// 查询统计条目
Integer aLong = jt.queryForObject("SELECT count(id) FROM demo", Integer.class);
System.out.println(aLong);
注入JdbcTemplate
<!--注入druid阿里连接池-->
<bean class="com.alibaba.druid.pool.DruidDataSource" name="dataSource" destroy-method="close">
<property name="url" value="${jdbc.jdbcUrl}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!--将DruidDataSource作为属性注入JdbcTemplate-->
<bean class="org.springframework.jdbc.core.JdbcTemplate" name="jdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
注入Dao实现类
<!--将JdbcTemplate注入DEmoDaoImpl-->
<bean class="cn.Pu1satilla.Dao.DemoDaoImpl" name="dao">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
类似可以将被注入dao层的Service层注入Spring容器
spring中aop事务
spring事务操作对象
因为不同平台(hibernate、mybatis、springJdbc)对事务操作的代码不同,spring想操作不同平台的事务,提供PlatforTransactiionManager接口,并提供相应平台的实现类。
- (springJdbc)DataSourceTransactionManager
- (hibernate)HibernateTransactionManager
注意:在spring中事务管理最为核心的对象就是TransactionManager对象
通过这些类的方法完成spring对事务操作
spring管理事务的属性
- 事务隔离级别(isolation)
- 读未提交
- 读已提交
- 可重复读
- 串行化
- 是否只读(read-only)
- true
- false
- 事务的传播行为(propagation)
- PROPACATION_REQUIED:支持当前事务,如果不存在就新建一个(默认)
- PROPAGATION_SUPPORTS:支持当前事务,如果不存在,就不使用事务
- PROPAGATION_MANDATORY:支持当前事务,如果不存在,抛出异常
- PROPAGATION_REQUIRES_NEW:如果有事务存在,挂起当前事务,创建一个新的事务
- PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果有事务存在,挂起当前事务
- PROPAGATION_NEVER:以非事务方式运行,如果有事务存在,抛出异常
- PROPAGATION_NESTED:如果当前事务存在,则嵌套事务执行
spring管理事务的方式
完成Dao层以及service层设计
JdbcDaoSupport
JdbcDaoSupport作用:此基类主要用于JdbcTemplate使用,但也可以在直接使用Connection或使用org.springframework.jdbc.object操作对象时使用 。多用于Dao层类继承,可以简化Dao层类代码
Dao类
package cn.Pu1satilla.dao;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
/*
* @Classname: AccountDaoImpl
* @Description: Dao层完成转账操作,实现JdbcDaoSupport,该类简化Dao实现。声明了jdbcTemplate属性
* @Author fy [939902332feng@gmail.com]
* @Date 2018/5/16 17:05
*
*/
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {
/**
* 收款人收账
*
* @param id 收账人id
* @param money 收账金额
*/
@Override
public void addMoney(Integer id, Double money) {
getJdbcTemplate().update("UPDATE account SET money=money+? WHERE id=?", money, id);
}
/**
* 转账人转账
*
* @param id 转账人id
* @param money 转账金额
*/
@Override
public void decreaseMoney(Integer id, Double money) {
getJdbcTemplate().update("UPDATE account SET money=money-? WHERE id=?", money, id);
}
}
Servcie层类
package cn.Pu1satilla.dao;
/*
* @Classname: AccountServiceImpl
* @Description: 业务层转账操作,实现AccounService接口,演示spring中aop事务操作的service层
* @Author fy [939902332feng@gmail.com]
* @Date 2018/5/16 17:27
*
*/
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
/**
* 通过spring aop配置完成事务方法切入
*
* @param from 转账人id
* @param to 收款人id
* @param money 转账金额
*/
@Override
public void transfer(int from, int to, double money) {
// 转账人金额
accountDao.decreaseMoney(from, money);
// 测试出现异常,spring提供aop事务操作是否有效
int i = 1 / 0;
// 收款人金额
accountDao.addMoney(to, money);
}
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
}
测试类
package cn.Pu1satilla.demo;
import cn.Pu1satilla.dao.AccountService;
import cn.Pu1satilla.dao.AccountServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/*
* @Classname: demo
* @Description: 测试类,测试转账事务是否通过spring aop配置成功
* @Author fy [939902332feng@gmail.com]
* @Date 2018/5/16 18:26
*
*/
public class demo {
public static void main(String[] args) {
// 1.建立spring 容器
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
// 2.获取容器中service对象
AccountService accountService = (AccountService) applicationContext.getBean("accountService");
// 3.调用dao对象转账方法
accountService.transfer(1,2,100);
}
}
xml配置(aop)
导入约束
<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">
DataSource导入配置文件内容
<!--从配置文件注入DruidDataSource-->
<context:property-placeholder location="DruidUtils.properties"/>
<bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="url" value="${jdbc.jdbcUrl}"/>
<property name="username" value="${jdbc.username}"/>
<property name="initialSize" value="${jdbc.initialSize}"/>
<property name="minIdle" value="${jdbc.minIdle}"/>
<property name="maxActive" value="${jdbc.maxActive}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
配置事务核心管理类
指定操纵事务的属于哪个平台,因为不同平台的事务操作的代码不相同,spring通过一个接口将不同平台的事务操作整合到一起,封装起来,其接口实现类对应不同平台,需要事先配置指定控制事务的属于哪个平台。
<!--配置事务核心管理类,封装了所有事务操作(对应SpringJdbc平台),
事务由connection控制,所以依赖于连接池,注入连接池-->
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" name="transactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
将DataSource注入dao
将连接池注入dao,dao类可以继承JdbcSupportDao类,具有方法getJdbcTemplate可直接获得JdbcTemplate,通过xml配置就能注入,无需再次声明
<!--将连接池注入Dao-->
<bean name="accountDao" class="cn.Pu1satilla.dao.AccountDaoImpl">
<property name="dataSource" ref="dataSource"/>
</bean>
将dao类注入到service
将dao注入service,并且声明dao属性
<!--注入Service-->
<bean name="accountService" class="cn.Pu1satilla.dao.AccountServiceImpl">
<!--注入Dao-->
<property name="accountDao" ref="accountDao"/>
</bean>
配置事务通知
<!--
配置事务通知
属性:
transaction-manager属性在配置文件中只存在单个其为默认
-->
<tx:advice id="txAdvice">
<tx:attributes>
<!--以方法为单位,指定方法应用说明事务属性
isolation:隔离级别
propagation:传播行为默认为PROPACATION_REQUIED 支持当前事务,如果不存在就新建一个
read-only:是否只读默认为false
-->
<tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
将通知织入切入点
<!--进行aop配置-->
<aop:config>
<!--配置切入点表达式,哪些类哪些方法需要被通知-->
<aop:pointcut id="TS" expression="execution(* cn.Pu1satilla.dao.AccountServiceImpl.transfer(..))"/>
<!--配置切面:通知+切面-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="TS"/>
</aop:config>
整体配置
<?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">
<!--从配置文件注入DruidDataSource-->
<context:property-placeholder location="DruidUtils.properties"/>
<bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="url" value="${jdbc.jdbcUrl}"/>
<property name="username" value="${jdbc.username}"/>
<property name="initialSize" value="${jdbc.initialSize}"/>
<property name="minIdle" value="${jdbc.minIdle}"/>
<property name="maxActive" value="${jdbc.maxActive}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!--将连接池注入Dao-->
<bean name="accountDao" class="cn.Pu1satilla.dao.AccountDaoImpl">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--配置事务核心管理类,封装了所有事务操作(对应SpringJdbc平台),
事务由connection控制,所以依赖于连接池,注入连接池-->
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" name="transactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--注入Service-->
<bean name="accountService" class="cn.Pu1satilla.dao.AccountServiceImpl">
<!--注入Dao-->
<property name="accountDao" ref="accountDao"/>
</bean>
<!--
配置事务通知
属性:
transaction-manager属性在配置文件中只存在单个其为默认
-->
<tx:advice id="txAdvice">
<tx:attributes>
<!--以方法为单位,指定方法应用说明事务属性
isolation:隔离级别
propagation:传播行为默认为PROPACATION_REQUIED 支持当前事务,如果不存在就新建一个
read-only:是否只读默认为false
-->
<tx:method name="transfer" isolation="REPEATABLE_READ"/>
</tx:attributes>
</tx:advice>
<!--进行aop配置-->
<aop:config>
<!--配置切入点表达式,哪些类哪些方法需要被通知-->
<aop:pointcut id="TS" expression="execution(* cn.Pu1satilla.dao.AccountServiceImpl.transfer(..))"/>
<!--配置切面:通知+切面-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="TS"/>
</aop:config>
</beans>
注解配置(aop)
配置事务管理核心类
与xml一致,都是为了指定管理事务的平台
<!--配置事务核心管理类,封装了所有事务操作(对应SpringJdbc平台),
事务由connection控制,所以依赖于连接池,注入连接池-->
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" name="transactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
开启注解管理事务
<!--开启注解管理事务,
属性:transaction-manager
在配置文件中只存在单个其为默认
-->
<tx:annotation-driven />
添加注解
在需要使用事务类方法或类上使用注解
@Transactional(isolation = Isolation.REPEATABLE_READ,propagation = Propagation.REQUIRED)
public void transfer(int from, int to, double money) {
// 转账人金额
accountDao.decreaseMoney(from, money);
// 测试出现异常,spring提供aop事务操作是否有效
// int i = 1 / 0;
// 收款人金额
accountDao.addMoney(to, money);
}
在类跟方法上添加注解区别:类上方添加注解使整个类的方法都实现增强事务;方法上方添加注解使单个方法实现增强事务,当某个特殊方法需要使用不同属性注解方式,可以现在类上添加普遍注解,再在单独类上添加特殊注解。