Spring 框架集成 JDBC:
-
概述:
- Spring框架中提供了很多持久层的模板类来简化编程,使用模板类写程序会变得简单
- template 模板:
- 都是 Spring 框架提供 XXXTemplate 模板
- Spring 框架提供了 JDBC 模板
- JdbcTemplate 类:Connection 表示连接,管理事务 Statement ResultSet
-
JDBC 模板类的使用:
- 方法:
- execute方法:用于执行任何 SQL 语句,一般用于执行 DDL 语句
- update、batchUpdate 方法:用于执行新增、修改和删除等语句
- query 和 queryForXXX 方法:用于执行相关查询语句
- call 方法:用于执行数据存储过程和函数相关的语句
- 添加依赖:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.3.21</version> </dependency> <!--mysql驱动包--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.13</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>5.0.2.RELEASE</version> </dependency> </dependencies>
- 创建实体类:
public class User { private Integer id; private String username; private Date birthday; private String sex; private String address; //get set方法 }
- Application 中配置数据库和 jdbcTemplate 参数:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" 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"> <!--配置连接DriverManagerDataSource --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis_demo"/> <property name="username" value="root"/> <property name="password" value="2020"/> </bean> <!-- 配置jdbcTemplate --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> </beans>
- 实现增删改查操作:
- 注意查询操作:
public class JDBCTemplate { ApplicationContext ctx=null; JdbcTemplate jdbc =null; { ctx=new ClassPathXmlApplicationContext("application.xml"); jdbc =(JdbcTemplate) ctx.getBean("jdbcTemplate"); } //插入 @Test public void testInsert(){ String sql="insert into user(username,address) values('李连杰','上海')"; jdbc.execute(sql); } //修改 @Test public void testUpdate(){ String sql = "update user set username = '张',address = '广东' where id = ?"; int res = jdbc.update(sql,2); } //删除 @Test public void testDelete(){ String sql = "delete from user where id = ?"; int res = jdbc.update(sql,15); System.out.println(res); } //查询 @Test public void testQuery(){ String sql = "select * from user where id = 6"; List<User> users = jdbc.query(sql,new BeanPropertyRowMapper<>(User.class)); for(User user : users){ System.out.println(user); } } }
- 注意查询操作:
- 方法:
-
使用 Spring 框架来管理模板类:
- 刚才编写的代码是使用 new 的方式,应该把这些交给 Spring 框架来管理
- Spring 管理内置的连接池:
<?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" 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"> <!-- 配置连接池 --> <bean name="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql:///test" /> <property name="username" value="root"/> <property name="password" value="root"/> </bean> <!-- 配置 jdbc 模板--> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"/> </bean> </beans>
- 编写测试方法:
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:application-jdbc.xml") public class AppTest { @Autowired private JdbcTemplate jdbcTemplate; @Test public void run(){ jdbcTemplate.update("insert into t_mvcc values (null,?)","张洪川"); } }
-
Spring 框架管理开源的连接池:
- 导入坐标:
<dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.10</version> </dependency>
- 编写配置文件:jdbc.properties
jdbc.driverClassName = com.mysql.jdbc.Driver jdbc.url = jdbc:mysql:///test jdbc.username = root jdbc.password = root
- 编写核心配置:
<?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" 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"> <!-- 配置连接池,使用的是Spring框架的内置连接池 --> <bean id="dataSourc" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql:///test"/> <property name="username" value="root"/> <property name="password" value="root"/> </bean> <!-- 使用开源连接池 --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="url" value="jdbc:mysql:///test"/> <property name="username" value="root"/> <property name="password" value="root"/> </bean> <!-- 加载属性文件 --> <bean id="placeholderConfigurer" class="org.springframework.beans.factory.config.PropertyOverrideConfigurer"> <property name="location" value="classpath:jdbc.properties"/> </bean> <!-- 第二种写法: 使用提供标签的方式 --> <context:property-placeholder location="classpath:jdbc.properties" /> <!-- 加载属性文件 --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <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> <!-- 配置 jdbc 模板 --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"/> </bean> </beans>
- 导入坐标:
-
Spring 框架的 JDBC 模板的简单操作:
- 编写实现类,对数据进行封装:
public class BeanMapper implements RowMapper<Person> { @Override public Person mapRow(ResultSet resultSet, int i) throws SQLException { Person person = new Person(); person.setId(resultSet.getInt("id")); person.setName(resultSet.getString("name")); return person; } }
- 编写增删改查代码:
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(value = "classpath:application_druid.xml") public class JDBC_Demo { @Autowired private JdbcTemplate jdbcTemplate; //插入 @Test public void insert(){ jdbcTemplate.update("insert into t_mvcc values (null,?)","李四"); } //修改 @Test public void update(){ jdbcTemplate.update("update t_mvcc set name = ? where name = ?","张三","李四"); } //删除 @Test public void delete(){ jdbcTemplate.update("delete from t_mvcc where name = ?","张三"); } //通过 id 查询 @Test public void selectById(){ System.out.println(jdbcTemplate.queryForObject("select * from t_mvcc where id = ?",new BeanMapper(),1)); } //查询所有数据 @Test public void selectAll(){ System.out.println(jdbcTemplate.query("select * from t_mvcc",new BeanMapper())); } }
- 编写实现类,对数据进行封装:
-
模拟转账开发:
-
编写 Doa 层:
public interface AccountDao { //付款 public void outMoney(String out, double money); //收款 public void inMoney(String in,double money); } public class AccountDaoImpl implements AccountDao { private JdbcTemplate jdbcTemplate; public void setJdbcTemplate(JdbcTemplate jdbcTemplate){ this.jdbcTemplate = jdbcTemplate; } //付款 @Override public void outMoney(String out, double money) { jdbcTemplate.update("update account set money = money - ? where name = ?",money,out); } //收款 @Override public void inMoney(String in, double money) { jdbcTemplate.update("update account set money = money + ? where name = ?",money,in); } }
-
编写 Service 层:
public interface AccountService { //转账方法 public void pay(String out,String in,double money); } public class AccountServiceImpl implements AccountService { private AccountDao accountDao; public void setAccountDao(AccountDao accountDao){ this.accountDao = accountDao; } @Override public void pay(String out, String in, double money) { //调用 Dao 层方法 accountDao.outMoney(out,money); accountDao.inMoney(in,money); } }
-
编写配置文件:
<?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" 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"> <!-- 第二种写法: 使用提供标签的方式 --> <context:property-placeholder location="classpath:jdbc.properties" /> <!-- 加载属性文件 --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <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> <!-- 配置 jdbc 模板 --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 配置Service --> <bean id="accountDao" class="org.example.dao.Impl.AccountDaoImpl"> <property name="jdbcTemplate" ref="jdbcTemplate"/> </bean> <bean id="accountService" class="org.example.service.impl.AccountServiceImpl"> <property name="accountDao" ref="accountDao"/> </bean> </beans>
- 编写测试代码:
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(value = "classpath:application_druid.xml") public class AccountDemo { @Autowired private AccountService accountService; //测试转账方法 @Test public void testPay(){ accountService.pay("李连杰","张治中",500); } }
-
-
Dao 层编写方式(第二种方法):
- Dao 层编写:
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao { //付款 @Override public void outMoney(String out, double money) { this.getJdbcTemplate().update("update account set money = money - ? where name = ?",money,out); } //收款 @Override public void inMoney(String in, double money) { this.getJdbcTemplate().update("update account set money = money + ? where name = ?",money,in); } }
- Service 层编写:
public class AccountServiceImpl implements AccountService { private AccountDao accountDao; public void setAccountDao(AccountDao accountDao){ this.accountDao = accountDao; } @Override public void pay(String out, String in, double money) { //调用 Dao 层方法 accountDao.outMoney(out,money); accountDao.inMoney(in,money); } }
- 配置文件编写:
<?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" 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"> <!-- 第二种写法: 使用提供标签的方式 --> <context:property-placeholder location="classpath:jdbc.properties" /> <!-- 加载属性文件 --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <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="accountDao" class="org.example.dao.Impl.AccountDaoImpl"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 配置Service --> <bean id="accountService" class="org.example.service.impl.AccountServiceImpl"> <property name="accountDao" ref="accountDao"/> </bean> </beans>
- 测试类编写:
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(value = "classpath:application_druid.xml") public class AccountDemo { @Autowired private AccountService accountService; //测试转账方法 @Test public void testPay(){ accountService.pay("李连杰","张治中",500); } }
- Dao 层编写:
Spring 框架对事务的管理:
-
Spring 管理事务的接口:
- 事务管理接口:PlatfromTransactionManager
- 平台管理器。该接口有具体的实现类,根据不同的持久框架,需要选择不同的实现类:
- 如果使用的 Spring 的 JDBC 模板或者 MyBatis 框架,需要选择 DataSourceTransactionManager 实现类
- 如果使用的是 Hibernate 的框架,需要选择 HibernateTransactionManager 实现类
- 接口方法:
- void commit(TransationStatus status)
- void rollback(TransationStatus status)
- 平台管理器。该接口有具体的实现类,根据不同的持久框架,需要选择不同的实现类:
- 事务定义接口:TransactionDefinition
- 定义了事务隔离级别
- 定义了事务传播方式
- 事务管理接口:PlatfromTransactionManager
-
Spring 框架声明式事务管理:
- 配置文件形式:
<?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"> <!-- 使用提供标签的方式 --> <context:property-placeholder location="classpath:jdbc.properties"/> <!-- 加载属性的文件 --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <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="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 配置事务通知(没有自己编写的切面类,通知方法不需手动编写,Spring 框架提供)--> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!-- 对 pay 进行增强,设置隔离级别、传播行为、超时时间--> <tx:method name="pay" isolation="DEFAULT" propagation="REQUIRED"/> <tx:method name="find*" read-only="true"/> </tx:attributes> </tx:advice> <!-- 配置 AOP 的增强 --> <aop:config> <!-- Spring 框架提供系统通知,使用 advisor 标签--> <aop:advisor advice-ref="txAdvice" pointcut="execution(public void org.example.service.impl.AccountServiceImpl.pay(..))"/> </aop:config> <!-- 配置 Dao --> <bean id="accountDao" class="org.example.dao.Impl.AccountDaoImpl"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 配置 Service --> <bean id="accountService" class="org.example.service.impl.AccountServiceImpl"> <property name="accountDao" ref="accountDao"/> </bean> </beans>
- 配置文件 + 注解方式:
- 配置文件:
<?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"> <!-- 开启注解扫描 --> <context:component-scan base-package="org.example"/> <!-- 第二种写法: 使用提供标签的方式 --> <context:property-placeholder location="classpath:jdbc.properties"/> <!-- 加载属性文件 --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <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="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 配置 JDBC 模板类--> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 开始事务注解的支持 --> <tx:annotation-driven transaction-manager="transactionManager"/> </beans>
- Service 代码:
@Service @Transactional(isolation = Isolation.DEFAULT) public class AccountServiceImpl implements AccountService { @Autowired private AccountDao accountDao; @Override public void pay(String out, String in, double money) { //调用 Dao 层方法 accountDao.outMoney(out,money); //模拟异常 int i = 0/1; accountDao.inMoney(in,money); } }
- 配置文件:
- 纯注解方式:
@Configuration @ComponentScan(basePackages = "org.example") @EnableTransactionManagement //开启事务注解 public class SpringConfig { @Bean public DataSource creatDataSource(){ //创建连接池对象,Spring 框架内置了连接池对象 DriverManagerDataSource dataSource = new DriverManagerDataSource(); //设置连接参数 dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql:///test"); dataSource.setUsername("root"); dataSource.setPassword("root"); return dataSource; } //创建模板对象 @Bean(name = "jdbcTemplate") public JdbcTemplate createJdbcTemplate(@Qualifier("dataSource") DataSource dataSource){ JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); return jdbcTemplate; } //创建平台事务管理器对象 @Bean(name = "transactionManager") public PlatformTransactionManager createTransactionManager(@Qualifier("dataSource") DataSource dataSource){ DataSourceTransactionManager manager = new DataSourceTransactionManager(dataSource); return manager; } }
- 配置文件形式: