一、spring 数据访问哲学

  1、为避免持久化的逻辑分散在程序的各个组件中,数据访问的功能应到放到一个或多个专注于此的组件中,一般称之为数据访问对象(data access object,DAO)。

  2、良好的的Repository应以接口的形式向外暴露出去,服务对象通过接口访问Repository对象,这样做可以使服务对象很方便的进行测试,甚至可以创建mock来进行测试。

  3、数据访问层应该是与持久化技术无关的方式来进行访问的,这样可以使得切换底层的持久层框架对程序的其他地方所带来的影响最小。

服务对象与Repository之间的关系,服务对象不会处理数据访问,而是将其委托给Repository。

二、spring 的数据访问异常体系

  在使用原生的JDBC访问数据时,应用程序必须去捕获JDBC抛出的异常SQLException,而且大多数情况下,异常不会告诉你哪里出了问题、如何处理。

  spring JDBC提供的数据访问异常体系解决了这两个问题,spring提供了很多数据访问异常,分别描述了他们抛出时所对应的问题。spring为读取和写入数据的几乎所有错误都提供了异常。而且spring 提供的异常均继承自DataAccessException,该异常为运行时异常,所以在代码中不必强制去捕获。

这样做的好处是:

  • 开发者可以从底层繁琐复杂的技术细节中解脱出来。
  • 开发者可以选择自己感兴趣的异常进行处理 。

常见的spring异常

异常类 说明
CleanupFailureDataAccessException 执行 DAO 操作成功,但在释放数据资源时发生异常,如关闭 Connection 时发生异常。
ConcurrencyFailureException 并发地操作数据时发生异常,如无法获取乐观锁或悲观锁时、死锁引发的失败等场景。
DataAccessResourceFailureException 访问数据资源失败,如无法获取数据连接,无法获取 Hibernate 的会话等场景。
DataRetrievalFailureException 获取数据失败,如找不到对应主键的数据或使用了错误的列索引等场景。
DataSourceLookupFailureException 无法从 JNDI 中查找到数据源。
DataIntegrityViolationException 数据操作违反了数据一致性限制时抛出,如插入重复的主键或引用不存在的外键场景。
InvalidDataAccessApiUsageException 不正确地调用某一种持久化技术时抛出,如在 Spring JDBC 中查询对象在调用前没有事先进行编译操作,就会抛出该异常。这种异常主要是因为不正确地使用持久化技术而产生的。
InvalidDataAccessResourceUsageException 在访问数据源时使用了不正确的方法时抛出,如写错 SQL 语句。
PermissionDeniedDataAccessException 数据访问权限不足时抛出。如仅拥有只读权限却试图更改数
UncategorizedDataAccessException 其它未被分类的异常。
................ .................

为了使用spring 的数据访问异常,必须使用spring支持的数据访问模板。

三、数据访问模板

  模板方法将过程中与特定实现相关的部分委托给接口,接口的不同实现定义了过程中的具体行为。(设计模式中模板模式的案例?没看过源码,不确定是不是

  spring在进行数据访问过程中将固定的和可变的明确划分为两个不同的类:模板和回调。模板管理过程中固定的部分,回调处理自定义的数据访问代码。

  

模板与回调的职责,模板类处理固定部分:事物控制、管理资源以及异常处理,回调处理语句、绑定参数以及整理结果集。

   如果直接使用JDBC,可以使用JdbcTemplate,若使用ORM框架,可以考虑使用JpaTemplate或者HibernateTemplate等。

模板类  用途
jdbc.core.JdbcTemplate JDBC链接
jdbc.core.namedparam.NamedParameterJdbcTemplate 支持命名参数的JDBC链接
orm.ibatis.SqlMapClientTemplate IBATIS SqlMap客户端
orm.Jpa.JpaTemplate java持久化API的实体管理器
............ ...........

spring 提供的数据访问模板

四、数据源的配置

  spring多种数据源配置方式

  • JDBC驱动程序定义的数据源
  • JNDI查找的数据源
  • 连接池的数据源

    考虑到现在基本都是spring boot的天下了,基本也不使用XML配置了,故此仅给出java配置。

  1、JNDI数据源(没用过仅做记录)

    java配置: 

   @Bean
public JndiObjectFactoryBean dataSource(){
JndiObjectFactoryBean factoryBean = new JndiObjectFactoryBean();
factoryBean.setJndiName("jdbc/myProjectDS");//指定JNDI中资源的名称。
factoryBean.setResourceRef(true);//若运行在java服务器中需要设置为true
factoryBean.setProxyInterface(DataSource.class);
return factoryBean;
}

  2、数据源连接池

  常见的数据库连接池有以下几个:

  • Apache commons DBCP
  • c3p0
  • BoneCP
  • Druid

  java配置:    

     @Bean
public BasicDataSource dataSource(){
BasicDataSource ds = new BasicDataSource();
ds.setDriverClassName("org.h2.Driver");
ds.setUrl("jdbc:h2:tcp://localhost/~/test");
ds.setUsername("root");
ds.setPassword("123");
ds.setInitialSize(5);
ds.setMaxActive(10);
return ds;
}

  3、基于JDBC的驱动的数据源

    这种数据源是最简单的配置方式,spring 提供了三个这样的数据源类

  • DriverManagerDataSource:在每个连接请求时都会返回一个新建的链接
  • simpleDriverDataSOurce:与DriverManagerDataSource类似,不同的是他直接使用JDBC驱动
  • SingleConnectionDataSource:在每个连接请求时都会返回同一个连接,可认为是只有一个连接的池,该类不适合多线程的应用程序。

  

  @Bean
public DataSource dataSource(){
DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
driverManagerDataSource.setDriverClassName("org.mysql.Driver");
driverManagerDataSource.setUrl("url");
driverManagerDataSource.setUsername("root");
driverManagerDataSource.setPassword("1");
return driverManagerDataSource;
}

  4、嵌入式数据源,H2

    嵌入式数据源作为应用的一部分运行,而不是独立的数据库服务器,对生产环境没有啥用处,但对开发和测试而言是非常好的方案    

  @Bean
public DataSource dataSource(){
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("classpath:schema.sql")
.addScript("classpath:test-data.sql")
.build();
}

 五、使用JDBC模板

  spring共提供三个JDBC模板:

  • JdbcTemplate最基本的springJDBC模板,支持简单的JDBC数据库访问功能以及基于索引的参数查询
  • NamedParameterJdbcTemplate:该模板可以将值以命名参数的形式绑定到SQL中,而非简单的索引值。
  • SimpleJdbcTepmlate:已被废弃,不做介绍。

  1、首先需要配置一个JDBCTemplate,只需为期设置DataSource即可。

   代码如下 

    @Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource){
return new JdbcTemplate(dataSource);
}

  2、编写数据访问相关接口及实现类

    图省事,省去了接口类,实际使用过程中自行添加。

UserRepository类
 @Repository
public class UserRepository {
private JdbcOperations jdbcOperations;
@Autowired
public UserRepository(JdbcOperations jdbcOperations) {
this.jdbcOperations = jdbcOperations;
} public void addUser(User user){
jdbcOperations.update("insert into user (username,password,email) values(?,?,?) ",
user.getUsername(),user.getPassword(),user.getEmail());
}
public User findUser(String id){
return jdbcOperations.queryForObject("select * from user where id = "+id,(resultSet, i) -> User.builder()
.username(resultSet.getString("username"))
.password(resultSet.getString("password"))
.email(resultSet.getString("email"))
.id(resultSet.getLong("id"))
.build());
}
}

UserController类:

 @RestController
public class UserController {
private final UserRepository repository; @Autowired
public UserController(UserRepository repository) {
this.repository = repository;
} @GetMapping("/addUser")
public String aa(){
repository.addUser(User.builder()
.email("abc@aa.com")
.username("tom")
.password("123456")
.build());
return "succ";
} @GetMapping("/query/{id}")
public User queryUser(@PathVariable String id){
return repository.findUser(id);
}
}

  NamedParameterJdbcTemplate简单使用:

   配置

    @Bean
public NamedParameterJdbcTemplate jdbcTemplate(DataSource dataSource){
return new NamedParameterJdbcTemplate(dataSource);
}

   使用map绑定参数

 public void addUser(User user){
Map<String,Object> data = new HashMap<>(8);
data.put("username","zhangsan");
data.put("password","123456");
data.put("email","asd@asd.com");
data.put("id", 123432);
jdbcOperations.update("insert into user(username,password,email,id) values (:username,:password,:email,:id)",data);
}
JdbcOperations API(下次有空了总结哈):https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jdbc/core/JdbcOperations.html

Z、参考资料

  https://blog.csdn.net/deniro_li/article/details/82820966

  

spring data之JDBCTemplate学习笔记的更多相关文章

  1. JdbcTemplate学习笔记

    JdbcTemplate学习笔记 1.使用JdbcTemplate的execute()方法执行SQL语句 Java 代码 jdbcTemplate.execute("CREATE TABLE ...

  2. Spring实战第一章学习笔记

    Spring实战第一章学习笔记 Java开发的简化 为了降低Java开发的复杂性,Spring采取了以下四种策略: 基于POJO的轻量级和最小侵入性编程: 通过依赖注入和面向接口实现松耦合: 基于切面 ...

  3. Spring实战第八章学习笔记————使用Spring Web Flow

    Spring实战第八章学习笔记----使用Spring Web Flow Spring Web Flow是一个Web框架,它适用于元素按规定流程运行的程序. 其实我们可以使用任何WEB框架写流程化的应 ...

  4. #Spring实战第二章学习笔记————装配Bean

    Spring实战第二章学习笔记----装配Bean 创建应用对象之间协作关系的行为通常称为装配(wiring).这也是依赖注入(DI)的本质. Spring配置的可选方案 当描述bean如何被装配时, ...

  5. Spring Cloud微服务学习笔记

    Spring Cloud微服务学习笔记 SOA->Dubbo 微服务架构->Spring Cloud提供了一个一站式的微服务解决方案 第一部分 微服务架构 1 互联网应用架构发展 那些迫使 ...

  6. spring data jpa入门学习

    本文主要介绍下spring data jpa,主要聊聊为何要使用它进行开发以及它的基本使用.本文主要是入门介绍,并在最后会留下完整的demo供读者进行下载,从而了解并且开始使用spring data ...

  7. Spring Data Jpa 入门学习

    本文主要讲解 springData Jpa 入门相关知识, 了解JPA规范与Jpa的实现,搭建springboot+dpringdata jpa环境实现基础增删改操作,适合新手学习,老鸟绕道~ 1. ...

  8. Spring jdbctemplate学习笔记

    /*List<?> config = getDB(" select t.datavalue from sys_config t where t.configid = '15' & ...

  9. Spring 4.0.2 学习笔记(2) - 自动注入及properties文件的使用

    接上一篇继续, 学习了基本的注入使用后,可能有人会跟我一样觉得有点不爽,Programmer的每个Field,至少要有一个setter,这样spring配置文件中才能用<property> ...

随机推荐

  1. hdu-5650 so easy(水题)

    题目链接: so easy Time Limit: 2000/1000 MS (Java/Others)   Memory Limit: 65536/65536 K (Java/Others)Tota ...

  2. 2017人工智能元年,AI在喧嚣和质疑中一路走来

    前百度首席科学家吴恩达说:就像100年前的电力.20年前的互联网一样,AI也会改变每一个产业! 有人说,现在就像1995年,那一年,第一家互联网公司--网景上市,一天之内大涨208%,互联网正式登上历 ...

  3. 错误名称:Uncaught SyntaxError: Unexpected token <

    在AngularJS框架下:   控制台输出: 1.谷歌:Uncaught SyntaxError: Unexpected token < 2.火狐:SyntaxError: expected ...

  4. Maven(5)-优化和重构POM

    本文主要介绍如何优化pom,杜绝重复(DRY). 1)模块重复依赖: 2)坐标版本号重复: 3)兄弟依赖 一.项目骨架 上图说明: multi-module-project是一个有多个模块构成的项目, ...

  5. grep的用法(转)

    grep参数 -c  : 显示匹配的行数(就是显示有多少行匹配了): -n :显示匹配内容所在文档的行号: -i  :匹配时忽略大小写: -s :错误信息不输出: -v :输出不匹配内容: -o : ...

  6. Excel特殊格式的列

    1.根据前两列显示天时分格式,算出所需时间列的内容=DAY(O2-N2)&"天"&HOUR(O2-N2)&"小时"&MINUTE ...

  7. 外置式与增量式PID模板程序(51单片机c语言)

    外置式PID模板 #define MuBiaoCS 0 //目标常数 #define CHang_aCS 0 //比例常数 #define CHang_bCS 0 //积分常数 #define CHa ...

  8. nmap 快速扫描所有端口

    nmap -sT -sV -Pn -v xxx.xxx.xxx.xxx nmap -sS -p 1-65535 -v 192.168.1.254参数:-sS    TCP SYN扫描    nmap ...

  9. web安全之同源策略

    为什么使用同源策略?一个重要原因就是对cookie的保护,cookie 中存着sessionID .如果已经登录网站,同时又去了任意其他网站,该网站有恶意JS代码.如果没有同源策略,那么这个网站就能通 ...

  10. JavaScript中设置cookie的值

    cookie 与 session 是网页开发中常用的信息存储方式.Cookie是在客户端开辟的一块可存储用户信息的地方:Session是在服务器内存中开辟的一块存储用户信息的地方.JavaScript ...