第4章--数据访问

Spring JDBC

DAO (Data Access Object) 实现数据访问相关接口(接口和实现分离)

ORM (Object Relation Mapping) 对象关系映射:数据库中记录<->Java对象

Why Spring JDBC?

之前使用JDBC时:设置连接参数、打开连接、声明SQL语句、执行SQL、得到访问结果、执行程序特定的业务、处理捕获的异常、关闭连接语句和结果集等

Class.forName(JDBC_DRIVER); DriverManager.getConnection(DB_URL, USER, PASS); conn.createStatement(); 等等

真正需要关心的是:设置连接参数、SQL语句以及参数、执行程序特定业务

Spring JDBC:封装用户不需要关心的那些底层实现细节,通过接口暴露给用户,从而提高效率

DataSource:数据源--设置连接参数

包括了:驱动类名、数据库连接地址、用户名、密码

接口方法:getConnection

DateSource不是Spring提供的,而是JavaEE本身就提供的,而Spring提供了它的不同实现

配置:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" 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> <context:property-placeholder location="db.properties"/>

jdbcTemplate:数据库SQL语句及参数、异常处理

select -- queryForObject()

int rowCount = this.jdbcTemplate.queryForObject("select count(*) from user", Integer.class);

int countOfNamedJoe = this.jdbcTemplate.queryForObject("select count(*) from user where first_name = ?", Integer.class, "Joe");

int lastName = this.jdbcTemplate.queryForObject("select last_name from user where id = ?", new Object[]{1212L}, String.class);

// queryForObject提供了很多接口,比如例二和例三中parameter的位置不一样

insert/delete/update -- update()

this.jdbcTemplate.update("insert into user (first_name, last_name) values (?, ?)", "Meimei", "Han");

this.jdbcTemplate.update("update user set last_name = ? where id = ?)", "Li", 5276L);

this.jdbcTemplate.update("delete from user where id = ?)", Long.valueOf(userId));

create -- execute()

this.jdbcTemplate.execute("create table user (id int, first_name varchar(100), last_name varchar(100))");

通过RowMapper可以将返回的结果转换为一个个单个的Object对象:

// 返回一个Java对象
User user = this.jdbcTemplate.queryForObject(
"select first_name, last_name from user where id = ?",
new Object[] {1212L},
new RowMapper<User>() {
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
user.setFirstName(rs.getString("first_name"));
user.setLastName(rs.getString("last_name"));
return user;
}
});
// 返回一系列Java对象
List<User> users = this.jdbcTemplate.query(
"select first_name, last_name from user",
new RowMapper<User>() {
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
user.setFirstName(rs.getString("first_name"));
user.setLastName(rs.getString("last_name"));
return user;
}
});

定义JdbcTemplate:

public class JdbcExampleDao implements ExampleDao {
private JdbcTemplate jdbcTemplate;
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
} // ... DAO 接口实现
}

通过xml中的bean配置DAO

<bean id="exampleDao" class="com.netease.course.JdbcExampleDao">
<property name="dataSource" ref="dataSource"/>
</bean>

通过Annotation配置DAO

@Repository
public class JdbcExampleDao implements ExampleDao {
private JdbcTemplate jdbcTemplate; @Autowired
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
} // ... DAO 接口实现
}

// @Repository与Component相似,定义了一个bean并指明了是个DAO的bean

// @Autowired自动注入了setDataSource

使用实例:

1. 创建Maven工程

artifact-id: com.netease.course

group-id: spring-data

2. pom中添加spring容器的依赖

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.netease.course</groupId>
<artifactId>spring-data</artifactId>
<version>0.0.1-SNAPSHOT</version> <dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.2.1.RELEASE</version>
</dependency>
</dependencies> </project>

3. src/main/resources中创建spring的空的xml配置文件application-context.xml

<?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"
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"> </beans>

4. src/main/resources中创建database的配置文件db.properties

jdbc.driverClassName = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://localhost/dbname
jdbc.username = matt
jdbc.password = matt 

5. 在application-context.xml中配置数据源

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" 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>
<context:property-placeholder location="db.properties" />

6. src/main/java下创建包com.netease.course

7. 在com.netease.course包中创建DAO文件JdbcTemplateDao.java

@Repository
public class JdbcTemplateDao { private JdbcTemplate jdbcTemplate; @Autowired
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
} public void createTable() {
jdbcTemplate.execute("create table user (id int primary key, first_name varchar(100), "
+ "last_name varchar(100))");
}
}

8. 由于是通过Annotation配置的,所以需要在application-context.xml配置文件中说明

<context:component-scan base-package="com.netease.course" />

9. 在com.netease.course包中创建测试类TestData.java

public class TestData {

    public static void main (String[] args) throws Exception {

        ApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");

        JdbcTemplateDao dao = context.getBean("jdbcTemplateDao", JdbcTemplateDao.class);
dao.createTable(); ((ConfigurableApplicationContext) context).close();
} }

// 得到Annotation定义的Dao实例,并执行Dao中的方法

10. Run

Error:

11. 解决方法:在dependencies里加上dbcp的依赖

<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>

12. Run

报错

原因:com.mysql.jdbc.Driver就是定义在db.properties中的,需要添加MySQL的依赖

13. 添加MySQL驱动的依赖

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.25</version>
</dependency>

14. Run

15. extends the functionalities

// DAO.java
public void insertData() {
this.jdbcTemplate.update("insert into example values (1, ?, ?)", "Meimei", "Han");
this.jdbcTemplate.update("insert into example values (2, ?, ?)", "Lei", "Li");
} public int count() {
return this.jdbcTemplate.queryForObject("select count(*) from user", Integer.class);
} // Test.java
dao.insertData();
System.out.println(dao.count());

运行成功,打印2

16. 将返回结果转换为User对象:在com.netease.course包下创建User.java

private int id;
private String firstName;
private String lastName;
// 并写上setters和getters

在JdbcTemplateDao.java中

public List<User> getUserList() {
return this.jdbcTemplate.query("select * from example", new RowMapper<User>() {
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
user.setId(rs.getInt("id"));
user.setFirstName(rs.getString("first_name"));
user.setLastName(rs.getString("last_name"));
return user;
}
});
}

Test.java

List<User> users = dao.getUserList();
for (User user: users) {
System.out.println(user.getId() + ":" + user.getFirstName() + " " + user.getLastName());
}

运行返回:

1:Meimei Han

2:Lei Li

NamedParameterJdbcTemplate:为了解决复杂sql语句中包含过多?导致的混乱

例:

// NamedParameterJdbcTemplateDao.java
@Repository
public class NamedParameterJdbcTemplateDao { private NamedParameterJdbcTemplate namedParameterJdbcTemplate; @Autowired
public void setDataSource(DataSource dataSource) {
this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
} public int countOfUsersByFirstName(String firstName) {
String sql = "select count(*) from example where first_name = :first_name";
Map<String, String> namedParameters = Collections.singletonMap("first_name", firstName);
return this.namedParameterJdbcTemplate.queryForObject(sql, namedParameters, Integer.class);
// 将map传递给queryForObject()作为参数,namedParameterJdbcTemplate会自动的匹配对应的参数名称的值,并组装成完整的sql
}
} // Test.java
NamedParameterJdbcTemplateDao dao = context.getBean("namedParameterJdbcTemplateDao", NamedParameterJdbcTemplateDao.class);
System.out.println(dao.countOfUsersByFirstName("Meimei"));

queryForObject的用法:

queryForObject(String sql, Map<String,?> paramMap, RowMapper<T> rowMapper)

queryForObject(String sql, SqlParameterSource paramSource, Class<T> requiredType)

可通过SqlParameterSource的子类BeanPropertySqlParameterSource来简化过程

SQLException异常处理:

无法连接到数据库、sql语法错误、row/column不存在等

是一个checked exception:必须使用try-catch或throws解决

但是由于这些SQLException一旦出现,事实上整个程序是无法运行的

且需要不厌其烦地写这些try-catch

--> Spring中使用DataAccessException (是一种unchecked的exception)

--不需到处都写try-check和throws,只需在最终层写上一个try-catch即可

DataAccessException有很多很多细分的子类(在org.springframework.dao包下)

事务管理

背景:1. 使用JDBC事务和Hibernate事务的接口不同,导致兼容需要修改代码。

2. 若有众多事务需要管理,通过代码进行管理事务会十分繁琐、混乱

Spring事务管理:

优点:统一的事务编程模型,兼容不同底层

编程式事务及声明式事务(AOP)

PlatformTransactionManager:org.springframework.transaction

接口:

TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;

void commit(TransactionStatus status) throws TransactionException;

void rollback(TransactionStatus status) throws TransactionException;

实现:

DataSourceTransactionManager:基于JDBC的实现 org.springframework.jdbc.datasource

HibernateTransactionManager:基于Hibernate的实现 org.springframework.orm.hibernate*

-- 接口一致

TransactionDefinition:事务的定义

getName:事务名称

getIsolationLevel:隔离级别

getPropagationBehavior:传播行为

getTimeout:超时时间(超过则回滚)

isReadOnly:是否是只读事务

TransactionStatus:事务的状态

isNewTransaction:是否是新的事务

hasSavepoint:是否有savepoint(诊断,NESTED)

isCompleted:是否已完成

isRollbackOnly:事务结果是否是rollback-only(只有rollback一个结果而不会commit)

setRollbackOnly:设置事务为rollback-only(当TransactionTemplate时才会调用)

隔离级别:

ISOLATION_READ_UNCOMMITTED: 读未提交

ISOLATION_READ_COMMITTED: 读提交

ISOLATION_REPEATABLE_READ: 重复读

ISOLATION_SERIALIZABLE: 串行化

ISOLATION_DEFAULT: 默认:根据底层数据库而定

传播行为:跟事务本身属性无关,跟函数调用有关,影响了事务的提交状态

比如两个事务嵌套,事务间是相互影响的呢还是相互不影响的

值:

PROPAGATION_MANDATORY: 函数必须在一个事务中运行,事务不存在则抛异常(比如在调用某函数之前,必须要存在一个事务,否则该函数抛异常)

PROPAGATION_NEVER: 不应该在事务中运行,否则抛异常

PROPAGATION_NOT_SUPPORTED: 不应该在事务中运行,否则把事务挂起

PROPAGATION_SUPPORTS: 不需要事务,但是若有事务了,则在事务中执行

PROPAGATION_REQUIRED: 必须在事务中执行,否则启动新事务

内部事务会影响外部事务:设T1调用了T2,若T2抛出异常,会影响外部的T1,因此T1和T2都要rollback

PROPAGATION_NESTED: 必须在事务中执行,否则启动新事务

事务之间相互不影响:上述T2的异常不会影响T1,只需rollback T2

从底层实现来看,每个logical的transaction都有自己的一个savepoint,失败时回滚到savepoint即可

PROPAGATION_REQUIRES_NEW: 必须在新事务中执行,挂起当前事务(即每个logical事务都对应一个独立的physical事务)

NB: 设代码中的transactionA调用了transactionB,看起来是两个Transaction,但是在底层数据库实现时,很可能把这两个视为一个数据库事务

逻辑事务 logical:比如上述transactionA和B

物理事务 physical:比如上述数据库事务

声明式事务:

在bean中添加配置

xmlns:aop="http://www.springframework.org/schema/aop"

xmlns:tx="http://www.springframework.org/schema/tx"

对应location:

xsi:schemaLocation="

http://www.springframework.org/schema/tx

http://www.springframework.org/schema/tx/spring-tx.xsd

http://www.springframework.org/schema/aop

http://www.springframework.org/schema/aop/spring-aop.xsd"

定义事务管理器:

<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>

定义事务Advice:(事务是基于AOP实现的)

<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="get*" read-only="true"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>

配置<tx:method/>

name:匹配的函数名称(支持*匹配)

propagation:事务传播行为

isolation:事务隔离级别

timeout:超时

read-only:只读

rollback-for:触发回滚的异常,用逗号分隔

no-rollback-for:不触发回滚的异常(正常提交),用逗号分隔

本例:

事务Advice应用到get*方法上,是read-only="true"的

事务Advice应用到get*方法上,使用默认隔离方式、默认隔离级别和默认传播行为等

定义Pointcut:(AOP)

<aop:config>
<aop:pointcut expression="execution(* com.netease.course.AccountDao.*(..))" id="daoOperation"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="daoOperation"/>
</aop:config>

使用声明式事务,需要定义很多的xml配置

Spring也提供了Annotation的方式来声明:

@Transactional

<tx:annotation-driven transaction-manager="txManager"/>
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>

配置属性:

value:使用哪一个TransactionManager

propagation:事务传播行为

isolation:事务隔离级别

timeout:超时

readOnly:只读

rollbackFor:触发回滚的异常类对象数组(是.class对象)

rollbackForClassName:触发回滚的异常类名称数组(是名称)

noRollbackFor/noRollbackForClassName:不触发回滚

具体函数的Annotation例子:

@Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)
public boolean methodName(..) {...}

实例:转账

Account.java

public class Account {
private String user;
private double balance; public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
}

AccountDao.java

@Repository
public class AccountDao {
private JdbcTemplate jdbcTemplate; @Autowired
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
} public void resetMoney() {
jdbcTemplate.update("update account set balance=1000");
} public List<Account> accountList() {
return this.jdbcTemplate.query("select * from account", new RowMapper<Account>() {
public Account mapRow(ResultSet rs, int rowNum) throws SQLException {
Account account = new Account();
account.setUser(rs.getString("user"));
account.setBalance(rs.getDouble("balance"));
return account;
}
});
} public void transferMoney(String source, String target, double amount) {
this.jdbcTemplate.update("update account set balance=balance-? where user=?", amount, source);
this.jdbcTemplate.update("update account set balance=balance+? where user=?", amount, target);
}
}

Test.java

public static void main (String[] args) throws Exception {

    ApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");

    AccountDao dao = context.getBean("accountDao", AccountDao.class);

    dao.resetMoney();
List<Account> accountList = dao.accountList();
for(Account account: accountList) {
System.out.println(account.getUser() + ":" + account.getBalance());
} dao.transferMoney("Kimi", "Miki", 520);
accountList = dao.accountList();
for(Account account: accountList) {
System.out.println(account.getUser() + ":" + account.getBalance());
} ((ConfigurableApplicationContext) context).close();
}

运行:

事务测试:

在dao中添加private void throwException(){ throw new RuntimeException("ERROR"); }

在两次update之间调用throwException();

并在test.java中的transferMoney()周围写上try-catch块,catch中syso出e.getMessage();

运行:

转账操作失败,需要通过事务方式进行设定,全部失败或是全部成功

改进:使用事务来完成这些任务

在application-context.xml中加入schema/tx和schema/aop

在application-context.xml中加入<context:component-scan base-package="com.netease.course" /> 以使用Annotation

在transferMoney()定义加上@Transactional(propagation = Propagation.REQUIRED)

运行结果均为1000.0,正确

编程式事务:

TransactionTemplate:在回调里写相关事务操作即可,不需要关心何时commit何时rollback

PlatformTransactionManager的实现:

整合MyBatis

数据访问单元测验

本次得分为:11.00/11.00, 本次测试的提交时间为:2017-09-24
1单选(2分)

关于Spring JDBC说法错误的是:

  • A.简化访问数据库的代码,提高效率;
  • B.可以直接帮助我们将数据库记录转化成Java对象;2.00/2.00
  • C.更方便的异常处理;
  • D.可以帮助我们进行资源管理:连接的创建,关闭等;
2单选(2分)

关于Spring事务管理,说明不正确的是:

  • A.统一的事务管理模型;
  • B.声明式事务支持;
  • C.编程式事务支持;
  • D.不依赖于底层事务的实现;2.00/2.00
3单选(2分)

假设事务A,B的传播行为定义为PROPAGATION_REQUIRED,由A事务会调用B事务,如果B事务抛出异常,并由A事务中代码捕获,那么A事务是否可以正常提交:

  • A.以上说法都不对;
  • B.不能提交;2.00/2.00
  • C.可以提交;
  • D.由A事务确定;
4多选(3分)

关于SQLException和DataAccessException,说明错误的是:

  • A.SQLException是Spring提供的异常类;1.50/3.00
  • B.DataAccessException是checked异常;1.50/3.00
  • C.DataAccessException是Spring提供的异常类;
  • D.SQLException是checked异常;
5判断(2分)

MyBatis通过Java Annotation写的Mapper必须通过接口(interface)来实现,不能通过类(class)。

  • A.×
  • B.√2.00/2.00

数据访问单元作业

http://zhanjingbo.site/14766902757975.html

1(12分)

根据本单介绍的Spring JDBC,事务管理,MyBatis等内容,分别使用Spring JDBC及MyBatis提供一个转帐服务(保证事务),提供一个transferMoney接口:

transferMoney(Long srcUserId, Long targetUserId, double count);// srcUserId及targetUserId为转帐用户标识

转帐涉及到的表(UserBalance)包含如下列:
userId:Long,代表用户标识;
balance:Doubcle,代表帐号余额。

基本要求:必须附加一个项目说明文档,说明每个功能点对应程序的运行结果(截图),项目的接口说明或者关键代码(不要把全部代码贴出来)等可以反映项目结果的内容。提交作业的时候必须有这个项目说明文档,否则会影响最终评分。

答:

1. 创建Spring的配置文件application-context.xml

<?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/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd" > <context:component-scan base-package="com.netease.course" /> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" 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> <tx:annotation-driven transaction-manager="txManager"/>
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean> <context:property-placeholder location="db.properties" />
</beans>

2. db.properties略

3. 创建Account.java

public class Account {
private int userId;
private double balance;
// 所需getters和setters
}

4a. 使用Spring JDBC实现AccountDao

@Repository
public class AccountDao {
private JdbcTemplate jdbcTemplate; @Autowired
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
} public void resetMoney() {
jdbcTemplate.update("update account set balance=1000");
} public List<Account> accountList() {
return this.jdbcTemplate.query("select * from account", new RowMapper<Account>() {
public Account mapRow(ResultSet rs, int rowNum) throws SQLException {
Account account = new Account();
account.setUserId(rs.getInt("id"));
account.setBalance(rs.getDouble("balance"));
return account;
}
});
}
@Transactional(propagation = Propagation.REQUIRED)
public void transferMoney(Long srcUserId, Long targetUserId, double count) {
// srcUserId及targetUserId为转帐用户标识
updateBalance(-count, srcUserId);
updateBalance(count, targetUserId);
} private void updateBalance(double count, Long userId) {
this.jdbcTemplate.update("update account set balance=balance+? where id=?", count, userId);
} private void throwException() {
throw new RuntimeException("UPDATE ERROR");
}
}

4b. 使用MyBatis实现AccountDao

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace=".matthew.dao.AccountDao">
<resultMap type="Account" id="AccountResult">
<result property="userId" column="userId" />
<result property="balance" column="balance" />
</resultMap>
<update id="reset">
update account set balance=1000
</update> <select id="getUserList" resultMap="AccountResult">
select * from account
</select>
<update id="updateBalance">
update account set balance=balance+#{param2} where userId=#{param1}
</update>
</mapper>

5. main()

public static void main (String[] args) throws Exception {
ApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");
AccountDao dao = context.getBean("accountDao", AccountDao.class); dao.resetMoney();
List<Account> accountList = dao.accountList();
for(Account account: accountList) {
System.out.println(account.getUserId() + ":" + account.getBalance());
}
try {
dao.transferMoney(1L, 2L, 520);
} catch (Exception e) {
System.out.println(e.getMessage());
}
accountList = dao.accountList();
for(Account account: accountList) {
System.out.println(account.getUserId() + ":" + account.getBalance());
}
((ConfigurableApplicationContext) context).close();
}

6. 运行结果

7. 模拟exception throw测试

在transferMoney()中的两个update之间调用throwException();

8. 运行结果


Java开发工程师(Web方向) - 04.Spring框架 - 第4章.数据访问的更多相关文章

  1. Java开发工程师(Web方向) - 04.Spring框架 - 第2章.IoC容器

    第2章.IoC容器 IoC容器概述 abstract: 介绍IoC和bean的用处和使用 IoC容器处于整个Spring框架中比较核心的位置:Core Container: Beans, Core, ...

  2. Java开发工程师(Web方向) - 04.Spring框架 - 第1章.Spring概述

    第1章.Spring概述 Spring概述 The Spring Framework is a lightweight solution and a potential one-stop-shop f ...

  3. Java开发工程师(Web方向) - 04.Spring框架 - 第3章.AOP技术

    第3章--AOP技术 Spring框架 - AOP概述 笔记https://my.oschina.net/hava/blog/758873Spring框架 - AOP使用 笔记https://my.o ...

  4. Java开发工程师(Web方向) - 04.Spring框架 - 第5章.Web框架

    第5章--Web框架 Web框架概述 Web框架单元测验 本次得分为:13.50/15.00, 本次测试的提交时间为:2017-09-25 1单选(2分) 关于Spring MVC中Dispatche ...

  5. Java开发工程师(Web方向) - 04.Spring框架 - 期末测试

    Spring框架客观题 Spring框架编程题 http://blog.csdn.net/sinoacc/article/details/51702458 1 (25分) 假设有如下数据表: crea ...

  6. Java开发工程师(Web方向) - 02.Servlet技术 - 第3章.Servlet应用

    第3章.Servlet应用 转发与重定向 转发:浏览器发送资源请求到ServletA后,ServletA传递请求给ServletB,ServletB生成响应后返回给浏览器. 请求转发:forward: ...

  7. Java开发工程师(Web方向) - 02.Servlet技术 - 第4章.JSP

    第4章--JSP JSP JSP(Java Server Pages) - 中文名:Java服务器页面 动态网页技术标准 JSP = Html + Java + JSP tags 在服务器端执行,返回 ...

  8. Java开发工程师(Web方向) - 02.Servlet技术 - 第2章.Cookie与Session

    第2章--Cookie与Session Cookie与Session 浏览器输入地址--HTTP请求--Servlet--HTTP响应--浏览器接收 会话(session):打开浏览器,打开一系列页面 ...

  9. Java开发工程师(Web方向) - 02.Servlet技术 - 第1章.Servlet

    第1章--Servlet Servlet简介 Servlet应用于? 浏览器发出HTTP请求,服务器接收请求后返回响应给浏览器. 接收请求后到返回响应之间: 服务器将请求对象转交给Servlet容器 ...

随机推荐

  1. Word中高效输入公式:内嵌公式和Mathtype

    Word中高效输入公式:内嵌公式和Mathtype 前言:对于理工科学生而言,公式输入必不可缺.LaTeX相比Word,在公式输入及排版方面更强大.但是对于轻量级的任务,用Word而言更加轻便(起码不 ...

  2. maven编译package慢

    mvn package编译出现连接不上mvn库的问题: [root@localhost nnnnn]# mvn package[INFO] Scanning for projects...Downlo ...

  3. 以EF形式操作mysql数据库

    1.引入Nuget包: 2.书写EF操作上下文 public class MySqlContext:DbContext { protected override void OnConfiguring( ...

  4. spring配置redis(xml+java方式)(最底层)

    条件:引用好架包 <dependency> <groupId>org.springframework.data</groupId> <artifactId&g ...

  5. 美化浏览器JSON格式

    工具下载地址: https://github.com/weibanggang/JSON-handle 原始 优化后 直接将文件拖到浏览器即可

  6. HDU 1078 FatMouse and Cheese ( DP, DFS)

    HDU 1078 FatMouse and Cheese ( DP, DFS) 题目大意 给定一个 n * n 的矩阵, 矩阵的每个格子里都有一个值. 每次水平或垂直可以走 [1, k] 步, 从 ( ...

  7. docker build

    nginx Docfile ----------------------- FROM centos   MAINTAINER daniel   RUN yum install -y wget RUN ...

  8. layui form表单 input输入框获取焦点后 阻止Enter回车自动提交

    最简单的解决办法,不影响其他操作,给提交按钮增加 type="button" 属性 完美解决 <button type="button" class=&q ...

  9. 【LAMP整合Redis键值缓存为库分担压力】

    LAMP+ redis 架构图: 安装phpredis扩展 Php主配置文件引入redis库文件 Redis扩展 // 对httpd php扩展连接指定redis服务器

  10. 浅谈CSS高度坍塌

    高度坍塌情况: 当父元素没有设置高度,且子元素块都向左(右)浮动起来,那么父元素就会出现坍塌的现象. 解决办法: 在父元素包含块中加一个div: 优点:兼容性强,适合初学者. 缺点:不利于优化. 方法 ...