JDBC模版:
和数据库交换(类似于DBUtils)★
spring是一个一栈式框架,提供了dao层支持
1.jdbc模版
2.orm模块
入门案例:转账账户的添加
整合dbcp
步骤:
1.导入jar (2个jar包 dbcp+pool) 可以在依赖包找 org.apache.commons
2.配置dbcp数据源 BasicDataSource
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///s04_62"/>
<property name="username" value="root"/>
<property name="password" value="1234"/>
</bean>
★整合c3p0
步骤:
1.导入jar包(1个或2个) 可以在依赖包找 com.mchange.c3p0
2.配置c3p0数据源
将数据库的4个参数抽取成属性文件(properties)
在项目src目录下 创建一个jdbc.properties
在spring配置文件中 需要加载解析属性文件
<!-- 配置c3p0 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}"/>
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"/>
<property name="user" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
加载属性文件两种方式
方式1:通过bean标签(不太用)
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<!-- 指定属性文件位置 -->
<property name="location" value="classpath:jdbc.properties"/>
</bean>
★方式2:通过context标签
<context:property-placeholder location="classpath:jdbc.properties"/>
3.属性注入,编写类
配置文件
<!-- 管理jdbcTemplate -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="accoundDao" class="com.xx.a_hello.AccountDao">
<!-- 注入jdbc模版 -->
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
Dao类
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public void save(String name,int money){
jdbcTemplate.update("insert into account values(null,?,?)",name,money);
}
测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext1.xml")
public class TestJdbc {
@Autowired
private AccountDao1 accountDao;
@Test
public void save(){
accountDao.save("阿童木", 1000);
}
★jdbc模版的api(类似DBUtils)
cud操作:
update(String sql,Object … args)
query操作:
T queryForObejct(String sql,Class clazz,Object … args):返回的一行一列的值 聚合函数
T queryForObejct(String sql,RowMapper rowmapper,Object … args):返回的一行多列的值 一条记录
List query(String sql,RowMapper rowmapper,Object … args):返回的多行多列的值 多条记录(list)
RowMapper是一个接口,需要我们自己创建实现类,将记录封装长指定的对象(类似于ResultSetHandler)
class MyRowMapper implements RowMapper<Account>{
@Override
/**
* ResultSet:结果集 每行记录
* index:索引
*/
public Account mapRow(ResultSet rs, int index) throws SQLException {
//创建account对象
Account account = new Account();
//获取每个字段值 给对象set进去
account.setId(rs.getInt("id"));
account.setName(rs.getString("name"));
account.setMoney(rs.getInt("money"));
return account;
}
通过刚才的案例,我们需要在配置文件中声明一个jdbc模版,在dao中需要提供jdbc模版属性(set),还需要在配置文件中给dao注入jdbc模版.
但是后面会有很多个dao,每个dao都需要需要提供jdbc模版属性(set),还需要在配置文件中给dao注入jdbc模版.
spring就提供了一个JdbcDaoSupport,我们可以让所有的dao继承JdbcDaoSupport,这个类中就已经提供好了模版的set和get方法
还提供一个方法 setDataSource,我们如果给dao注入一个DataSource的话,里面会帮我们将jdbc模版创建出来.
这样的话就不需要在配置文件中声明jdbc模版
结论:
若我们使用的xml方式配置文件做的,我们就可以让所有的dao继承JdbcDaoSupport,在配置文件中给dao注入数据源即可.
若我们使用的注解方式就不能用以上方法.因为我们自己编写dao中没有dataSource属性,就不能在属性添加@AutoWired.但是可以使用声明jdbc模版,给dao注入模版()
声明式事务(通过配置给service层添加事务)
事务特性:acid
若不考虑隔离性会产生那些读问题
通过设置隔离级别解决上面的读问题
read uncommitted
read committed
repeatable read
serializable
事务加载service层.
spring中的事务控制
步骤:
搭建转账环境
1.新建web项目
导入jar包 14个+c3p0
2.提供一个accountservice,里面提供一个转账方法
3.提供一个accountDao,里面需要提供两个方法,加钱和减钱方法
4.将所有的bean交给spring管理
5.创建一个测试类,测试service.
spring中事务的api
PlatformTransactionManager:平台事务管理器 接口
★两个实现类:
DataSourceTransactionManager: 若dao层使用的jdbc和mybatis 就使用这个
HibernateTransactionManager: 若dao层使用的hibernate 就使用这个
TransactionDifinition:事务定义对象
指定事务的规则:
隔离级别
传播行为:常用值 REQUIRED和SUPPORTS 见excel说明
是否只读(默认值:false,只有在做查询的时候才设置为true,效率高)
超时信息(若值为-1:永不超时)
TransactionStatus:事务状态对象
★总结一句话:
spring执行事务的时候,先通过TransactionDifinition定义事务的规则,通过PlatformTransactionManager执行事务,执行的过程中会产生一些信息,这些信息最终保存在TransactionStatus对象中
大前提:
都需要声明事务管理器(需要注入datasource).
<!-- 声明事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 注入数据源 -->
<property name="dataSource" ref="dataSource"/>
</bean>
★使用xml方式控制事务
1.配置通知类(spring已经提供好了,我们需要指定规则)
<!-- 配置通知类:执行事务的规则 -->
<tx:advice transaction-manager="transactionManager" id="tx_advice">
<tx:attributes>
<!-- 开发中的格式:
<tx:method name="save*" isolation="DEFAULT" propagation="REQUIRED" timeout="-1" read-only="false"/>
<tx:method name="update*" isolation="DEFAULT" propagation="REQUIRED"/>
<tx:method name="delete*"/>
<tx:method name="find*" isolation="DEFAULT" propagation="SUPPORTS" read-only="true"/>
<tx:method name="get*" isolation="DEFAULT" propagation="SUPPORTS" read-only="true"/>
-->
<!--我们案例的配置-->
<tx:method name="account" isolation="DEFAULT" propagation="REQUIRED" timeout="-1" read-only="false"/>
</tx:attributes>
</tx:advice>
2.aop配置
<aop:config>
<!-- 定义切入点 -->
<!--
实际开发中配置
<aop:pointcut expression="execution(* com.xx.service..*.*(..))" id="pt1"/>
-->
<aop:pointcut expression="execution(* com.xx.b_xml.AccountService.*(..))" id="pt1"/>
<!-- 配置切面 -->
<aop:advisor advice-ref="tx_advice" pointcut-ref="pt1"/>
</aop:config>
★使用xml和注解混合方式控制事务
开发中一般
将bean的创建和注入交给spring管理
配置数据源,事务管理器,jdbc模版
在配置文件中
开启组件扫描
<!-- 开启组件扫描 -->
<context:component-scan base-package="com.xx.c_xml_anno"/>
开启事务注解支持
<tx:annotation-driven transaction-manager="transactionManager"/>
在service上添加注解
@Transactional
(了解)使用纯注解方式控制事务
基本没用过,只是了解下有这种方式
步骤:
加载属性文件
配置数据源
声明事务管理器
声明jdbc模版
开启组件扫描
开启事务注解支持 @EnableTransactionManagement
若上面的配置都可以通过注解来做,那么配置文件就可以删除了
SpringConfig 类
@Configuration
@ComponentScan(value="com.xx")
@PropertySource("classpath:jdbc.properties")
@Import(JdbcConfig.class)
@EnableTransactionManagement
public class SpringConfig {
@Bean
public static PropertySourcesPlaceholderConfigurer createPropertySourcesPlaceholderConfigurer(){
return new PropertySourcesPlaceholderConfigurer();
}
@Bean(name="jdbcTemplate")
/**
* @Qualifier("dataSource") 用来注入参数的
*/
public JdbcTemplate createJdbcTemplate(@Qualifier("dataSource") DataSource dataSource){
return new JdbcTemplate(dataSource);
}
@Bean(name="transactionManager")
public PlatformTransactionManager createPlatformTransactionManager(@Qualifier("dataSource") DataSource dataSource){
return new DataSourceTransactionManager(dataSource);
}
JdbcConfig 类
@Configuration
public class JdbcConfig {
@Value("${jdbc.driverClass}")
private String driverClass;
@Value("${jdbc.jdbcUrl}")
private String jdbcUrl;
@Value("${jdbc.user}")
private String user;
@Value("${jdbc.password}")
private String password;
@Bean(name="dataSource")
public DataSource createDataSource(){
ComboPooledDataSource ds = new ComboPooledDataSource();
try {
ds.setDriverClass(driverClass);
ds.setJdbcUrl(jdbcUrl);
ds.setUser(user);
ds.setPassword(password);
} catch (PropertyVetoException e) {
e.printStackTrace();
}
return ds;
}