一.JDBC
1.环境准备:
1. mysql-connector-java-5.1.x.jar:MySQL驱动包
2. druid-1.x.jar:德鲁伊连接池
3. spring-jdbc-4.2.4.RELEASE.jar:支持JDBC
4. spring-tx-4.2.4.RELEASE.jar: 支持事务
DDL
CREATE TABLE `t_emp` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`sal` decimal(10,0) DEFAULT NULL,
`hireDate` date DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
db.properties
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///struts2
jdbc.username=root
jdbc.password=admin
domain
Employee
@Setter@Getter@ToString
@AllArgsConstructor
@NoArgsConstructor
public class Employee {
private Long id;
private String name;
private BigDecimal sal;
private Date hireDate;
}
dao接口IEmployeeDAO
public interface IEmployeeDAO {
void save(Employee e);
void update(Employee e);
void delete(Long id);
Employee get(Long id);
List<Employee> queryList();
}
dao实现类
EmployeeDAOImpl
public class EmployeeDAOImpl implements IEmployeeDAO{
private JdbcTemplate jdbcTemplate;
//属性dataSource
public void setDataSource(DataSource ds) {
jdbcTemplate = new JdbcTemplate(ds);
}
public void save(Employee e) {
String sql = "insert t_emp values(null,?,?,?)";
Object[] params = {e.getName(),e.getSal(),e.getHireDate()};
jdbcTemplate.update(sql,params);
}
public void update(Employee e) {
String sql = "update t_emp set name=?,sal=?, hireDate=? where id=?";
Object[] params = {e.getName(),e.getSal(),e.getHireDate(),e.getId()};
jdbcTemplate.update(sql,params);
}
public void delete(Long id) {
String sql = "delete from t_emp where id=?";
jdbcTemplate.update(sql,id);
}
public Employee get(Long id) {
String sql = "select * from t_emp where id=?";
List<Employee> list= jdbcTemplate.query(sql, new RowMapper<Employee>() {
public Employee mapRow(ResultSet rs, int rewNum) throws SQLException {
Employee emp = new Employee();
emp.setId(rs.getLong("id"));
emp.setName(rs.getString("name"));
emp.setSal(rs.getBigDecimal("sal"));
emp.setHireDate(rs.getDate("hireDate"));
return emp;
}
},id);
return list.size() > 0 ? list.get(0) : null;
}
public List<Employee> queryList() {
String sql = "select * from t_emp";
List<Employee> list = jdbcTemplate.query(sql, new RowMapper<Employee>(){
public Employee mapRow(ResultSet rs, int rewNum) throws SQLException {
Employee emp = new Employee();
emp.setId(rs.getLong("id"));
emp.setName(rs.getString("name"));
emp.setSal(rs.getBigDecimal("sal"));
emp.setHireDate(rs.getDate("hireDate"));
return emp;
}
});
return list.size() > 0 ? list : null;
}
}
配置App-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:property-placeholder location="classpath:db.properties"
system-properties-mode="NEVER"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<bean id="employeeDAOImpl" class="cn.dusk._01_jdbc.dao.impl.EmployeeDAOImpl">
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
测试类App
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class App {
@Autowired
IEmployeeDAO dao;
@Test
public void testSave() throws Exception {
Employee e = new Employee(null,"真.红眼黑空",new BigDecimal("9000"),new Date());
dao.save(e);
}
@Test
public void testUpdate() throws Exception {
Employee e = new Employee(1L,"假.红眼黑空",new BigDecimal("8000"),new Date());
dao.update(e);
}
@Test
public void testDelete() throws Exception {
dao.delete(3L);
}
@Test
public void testGet() throws Exception {
Employee employee = dao.get(2L);
System.out.println(employee);
}
@Test
public void testList() throws Exception {
List<Employee> queryList = dao.queryList();
for (Employee employee : queryList) {
System.out.println(employee);
}
}
}
二.事务
- Spring的事务管理主要包括3个接口:
- TransactionDefinition:封装事务的隔离级别和超时时间,是否为只读事务和事务的隔离级别和传播规则等事务属性,可通过XML配置具体信息。
- PlatformTransactionManager:根据TransactionDefinition提供的事务属性配置信息,创建事务。
- TransactionStatus:封装了事务的具体运行状态。比如,是否是新开启事务,是否已经提交事务,设置当前事务为rollback-only等。
- Spring支持编程式事务管理和声明式事务管理。
- 编程式事务管理:事务和业务代码耦合度太高。
- 声明式事务管理:侵入性小,把事务从业务代码中抽离出来,提供维护性。
Spring的事务管理:
- PlatformTransactionManager:接口统一抽象处理事务操作相关的方法;
- TransactionStatus getTransaction(TransactionDefinition definition):
根据事务定义信息从事务环境中返回一个已存在的事务,或者创建一个新的事务,并用TransactionStatus描述该事务的状态。 - void commit(TransactionStatus status):
根据事务的状态提交事务,如果事务状态已经标识为rollback-only,该方法执行回滚事务的操作。 - void rollback(TransactionStatus status):
将事务回滚,当commit方法抛出异常时,rollback会被隐式调用
- TransactionStatus getTransaction(TransactionDefinition definition):
- 在使用spring管理事务的时候,首先得告诉spring使用哪一个事务管理器; 看图
- 常用的事务管理器:
DataSourceTransactionManager:使用JDBC,MyBatis的事务管理器:依赖DataSource对象;
HibernateTransactionManager: 使用Hibernate的事务管理器:依赖SessionFactory对象;
三.声明式事务管理-基于配置xml
DDL
CREATE TABLE `account` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`balance` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
资源文件
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///struts2
jdbc.username=root
jdbc.password=admin
dao接口
public interface IAccoutDAO {
void transOUt(Long outId,Integer money);
void transIn(Long inId,Integer money);
}
dao实现类
public class AccoutDAOImpl extends JdbcDaoSupport implements IAccoutDAO{
public void transOUt(Long outId, Integer money) {
String sql = "update account set balance = balance - ? where id=?";
getJdbcTemplate().update(sql,money,outId);
}
public void transIn(Long inId, Integer money) {
String sql = "update account set balance = balance + ? where id=?";
getJdbcTemplate().update(sql,money,inId);
}
}
service接口
public interface IAccountService {
void trans(Long outId,Long inId,Integer money);
}
service实现类
public class AccountServiceImpl implements IAccountService{
@Setter
private IAccoutDAO dao;
public void trans(Long outId, Long inId, Integer money) {
dao.transOUt(outId, money);
System.out.println(1/0);
dao.transIn(inId, money);
}
}
App-context.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 引入属性文件啊 -->
<context:property-placeholder location="classpath:db.properties"
system-properties-mode="NEVER"/>
<!-- 配置连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- 配置dao -->
<bean id="accoutDAOImpl" class="cn.dusk._02_routine.dao.impl.AccoutDAOImpl">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 配置service -->
<bean id="cccountServiceImpl" class="cn.dusk._02_routine.service.impl.AccountServiceImpl">
<property name="dao" ref="accoutDAOImpl"/>
</bean>
<!--what 配置事务管理器 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- when:配置事务的环绕增强 -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="trans"/>
</tx:attributes>
</tx:advice>
<!-- where:配置在哪里做增强 -->
<aop:config>
<aop:pointcut expression="execution(* cn.dusk._02_routine.service.*Service.*(..))" id="point"/>
<aop:advisor advice-ref="txAdvice" pointcut="point"/>
</aop:config>
</beans>
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class App {
@Autowired
private IAccountService service;
@Test
public void testOut() throws Exception {
service.trans(2L, 1L, 1000);
}
}
四.总结
一:spring基础
- bean管理原理
- 反射(创建对象[IoC]) + 内省(属性赋值[DI])
- xml配置
见详细配置表: 注意属性必须提供set方法 - 获取bean方式
容器对象.getBean(beanName)
容器对象.getBean(beanType)
容器对象.getBean(beanName, beanType) - bean的作用域
singleton(单例) prototype(多例)
二:IoC
- xml方式:
<bean id=".." class="...">
-
注解:
1)<context:component-scan base-package=""/>
@Service用于标注业务层组件 @Controller用于标注控制层组件(如struts中的action) @Repository用于标注数据访问组件,即DAO组件 @Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注
三:DI注入
给容器创建好的对象设置属性值
- 使用xml配置(见详细配置表)
- Setter注入
- 构造器注入
- 注解
- context:annotation-config/
- @Autowired: 先按类型, 再按名字
- @Resource: 先按名字,再按类型
四:AOP
- 动态代理:不改变源代码情况下动态添加功能
- JDK:通过接口实现
- CGLIB:通过类继承方式实现
2.AOP 3要素
英语:I had dinner at home last night - what: 要添加什么额外功能(增强)
- where: 在哪个位置作增强(哪个包,哪个类,哪个方法 )
- when: 在什么时机执行(执行前?后?异常?..)
五:事务
xml方式:
<bean id="事务管理器实例名称" class="事务管理器类全名">
<property name="数据源属性名" ref="要引用的数据源实例名称"/>
</bean>
<!-- 配置一个事务通知 -->
<tx:advice id="事务通知名称" transaction-manager="事务管理器实例名称">
<tx:attributes>
<!-- 方法以get/select/query开头,不使用事务 -->
<tx:method name="get*" read-only="true" propagation="NOT_SUPPORTED"/>
<tx:method name="select*" read-only="true" propagation="NOT_SUPPORTED"/>
<tx:method name="query*" read-only="true" propagation="NOT_SUPPORTED"/>
<!-- 其他方法以默认事务进行 -->
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<!-- 使用AOP技术实现事务管理 -->
<aop:config>
<aop:pointcut id="事务切入点名称" expression="事务切入点正则表达式" />
<aop:advisor advice-ref="事务通知名称" pointcut-ref="事务切入点名称"/>
</aop:config>