JavaWeb——Spring 系列
四、Spring AOP的 DAO
1、DAO 介绍
- DAO,Data Access Object,顾名思义适用于操作数据库的。Spring 的 DAO 是 O/R Mapping 技术的一种实现。
- Spring DAO 提供了如下几种抽象类:
- 1)jdbcDaoSupport:JDBC DAO 抽象类,当设置好数据源之后,通过子类可以获得 jdbcTemplate 来访问数据库。
- 2)HibernateDaoSupport:Hibernate DAO 抽象类,同样的配置号 Hibernate SessionFactory 后,通过子类可以获得 Hibernate 实现。
- 3)jdoDaoSupport:JDO DAO 抽象类,同样需要配置 PersistenceManagerFactory,通过子类可以获得 jdoTemplate。
2、Spring DAO 简单实例
- 首相建立一个 User 类,代码如下:
//IntelliJ IDEA //Sprin01 //User //2020/1/15 // Author:御承扬 //E-mail:2923616405@qq.com package com.myCode.DAOCode; public class User { private Integer id; private String name; private Integer age; private String sex; public void setId(Integer id) { this.id = id; } public Integer getId() { return id; } public void setName(String name) { this.name = name; } public String getName() { return name; } public void setAge(Integer age) { this.age = age; } public Integer getAge() { return age; } public void setSex(String sex) { this.sex = sex; } public String getSex() { return sex; } }
- 根据 User 的属性,在 MySQL 的是当数据库建立一个 user 表。
- 新建一个接口抽象类和一个实现类,代码如下:
package com.myCode.DAOCode; public interface UserDAOImpl { public void insertUser(User user); }
package com.myCode.DAOCode; import javax.sql.DataSource; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; public class UserDAO implements UserDAOImpl { private DataSource dataSource; public DataSource getDataSource() { return dataSource; } public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } @Override public void insertUser(User user) { String name = user.getName(); Integer age = user.getAge(); String sex = user.getSex(); Connection conn = null; Statement stmt = null; try { conn = dataSource.getConnection(); stmt = conn.createStatement(); stmt.execute(String.format("INSERT INTO user(name,age,sex)VALUES( '%s',%d,'%s')", name, age, sex)); } catch (SQLException e) { e.printStackTrace(); }finally { if(stmt!=null){ try{ stmt.close(); }catch (SQLException e){ e.printStackTrace(); } } if(conn != null){ try{ conn.close(); }catch (SQLException e){ e.printStackTrace(); } } } } }
- 接着在 ApplicationContext.xml 中配置:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8"/> <property name="username" value="root"/> <property name="password" value="******"/> </bean> <bean id="userDAO" class="com.myCode.DAOCode.UserDAO"> <property name="dataSource" ref="dataSource"/> </bean>
- 最后建立一个 Manager 类
package com.myCode.DAOCode; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; public class DAOManager { public static void main(String[] args) { Resource resource = new ClassPathResource("applicationContext.xml"); BeanFactory factory = new XmlBeanFactory(resource); User user = new User(); user.setName("张三"); user.setAge(20); user.setSex("男"); UserDAO userDAO = (UserDAO)factory.getBean("userDAO"); userDAO.insertUser(user); System.out.println("添加数据成功!!!"); } }
3、基于 AOP的DAO 模式的 Spring 事务
- Spring 的事务基于 AOP 实现的,由于 Spring 的 AOP 是以方法为单位的,所以 Spring 的事务属性就是对事务应用到方法上的策略描述。
- 事务的管理分为:编程式事务管理和声明式事务管理。
3.1、编程式事务管理
- Spring 中通过 PlatformTransactionManager 接口的事务管理器或 TransactionTemplate 实现编程式事务管理;后者更为符合 Spring 的模板模式。
- 示例
- 首先新建一个 TransactionExample,其代码如下:
package com.myCode.DAOCode.transaction; import org.springframework.jdbc.datasource.DataSourceUtils; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.TransactionCallback; import org.springframework.transaction.support.TransactionTemplate; import javax.annotation.Resource; import javax.sql.DataSource; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; @Resource(name = "transactionManager") public class TransactionExample { DataSource dataSource; //注入数据源 PlatformTransactionManager transactionManager; //注入事务管理器 TransactionTemplate transactionTemplate; //注入TransactionTemplate 模板 public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } public DataSource getDataSource() { return dataSource; } public void setTransactionManager(PlatformTransactionManager transactionManager) { this.transactionManager = transactionManager; } public PlatformTransactionManager getTransactionManager() { return transactionManager; } public void setTransactionTemplate(TransactionTemplate transactionTemplate) { this.transactionTemplate = transactionTemplate; } public TransactionTemplate getTransactionTemplate() { return transactionTemplate; } public void transactionOperation(){ transactionTemplate.execute(new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus transactionStatus) { Connection conn = DataSourceUtils.getConnection(dataSource);//获得数据库连接 try{ Statement stmt = conn.createStatement(); stmt.execute("insert into user(name,age,sex) values('小强',26,'男')"); int a=0; //制造异常测试事务是否配置成功 a=9/a; stmt.execute("insert into user(name,age,sex) values('Tonny',24,'女')"); System.out.println("执行成功"); }catch (Exception e){ transactionManager.rollback(transactionStatus); System.out.println("操作执行失败,事务回滚!"); System.out.println("原因:"+e.getMessage()); } return null; } }); } }
- 接着进行配置,配置代码如下:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8"/> <property name="username" value="root"/> <property name="password" value="********"/> </bean> <!--定义 TransactionTemplate模板--> <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"> <property name="transactionManager" ref="transactionManager"/> <property name="propagationBehaviorName" value="PROPAGATION_REQUIRED"/> </bean> <!-- 定义事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 为TransactionExample注入数据源 、事务管理器、TransactionTemplate模板--> <bean id="transactionExample" class="com.myCode.DAOCode.transaction.TransactionExample"> <property name="dataSource" ref="dataSource"/> <property name="transactionManager" ref="transactionManager"/> <property name="transactionTemplate" ref="transactionTemplate"/> </bean>
- 在建立一个 Manager类:
package com.myCode.DAOCode.manager; import com.myCode.DAOCode.transaction.TransactionExample; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TransactionManage { public static void main(String[] args) { BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml"); TransactionExample example = (TransactionExample)factory.getBean("transactionExample"); example.transactionOperation(); } }
3.2、声明式事务管理
- Spring 用 TransactionProxyFactoryBean 完成声明式事务管理,示例如下:
- 首先建立一个事务类,用于向 user 表插入数据,代码如下:
package com.myCode.DAOCode.DAO; import com.myCode.DAOCode.bean.User; import org.springframework.jdbc.core.support.JdbcDaoSupport; public class AddDAO extends JdbcDaoSupport{ public void addUser(User user){ String sql = String.format("insert into user(name,age,sex) values('%s',%d,'%s')",user.getName(),user.getAge(),user.getSex()); try{ assert getJdbcTemplate() != null; getJdbcTemplate().execute(sql); }catch (Exception e){ System.out.println("执行失败,原因:"+e.getMessage()); } } }
- 在 applicationContext.xml 文件中进行相关配置,如下:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8"/> <property name="username" value="root"/> <property name="password" value="*******"/> </bean> <!-- 定义TransactionProxy --> <bean id="transactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager" ref="transactionManager"/> <property name="target"> <bean class="com.myCode.DAOCode.DAO.AddDAO"> <property name="dataSource" ref="dataSource"/> </bean> </property> <property name="proxyTargetClass" value="true"/> <property name="transactionAttributes"> <props> <prop key="add*">PROPAGATION_REQUIRED</prop> </props> </property> </bean>
- 创建一个 Manager 类应用刚刚的配置
package com.myCode.DAOCode.manager; import com.myCode.DAOCode.DAO.AddDAO; import com.myCode.DAOCode.bean.User; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; public class ProxyManager { public static void main(String[] args) { BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml"); AddDAO addDAO = (AddDAO)factory.getBean("transactionProxy"); User user = new User(); user.setName("秋月白"); user.setAge(27); user.setSex("未知"); addDAO.addUser(user); } }