当前位置: 首页 > news >正文

④JdbcTemplate与声明式事务

JdbcTemplate

1.概述

前面我们已经学习了 Spring 中的Core Container核心部分和AOPAspects等面向切面编程部分,接下来就是Data Access/Integration即数据访问和集成部分

Spring 既可以单独使用,也可以集成其他框架,如HibernateMyBatis等。除此之外,其中对于JDBC也做了封装,即本章节的JdbcTemplate,用它可以比较方便地对数据库进行增删改查等操作

总结一下:

  • JdbcTemplate就是 Spring 框架对JDBC技术进行的二次封装模板,能够简化对数据库的操作

2.准备工作

2.1 相关SQL

DROP TABLE IF EXISTS `t_book`;
CREATE TABLE `t_book`  (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(25)  NOT NULL,`price` decimal(10, 2) ,PRIMARY KEY (`id`) 
);

2.2 步骤预览

  • 1)引入相关jar

  • 2)Spring 配置文件配置Druid连接池信息

  • 3)配置JdbcTemplate对象,注入dataSource

  • 4)创建 Service 和 Dao 类,在 Dao 类中注入JdbcTemplate对象

2.3 详细操作

  • 1)引入相关jar包(或依赖)

    • druid

    • mysql-connector-java

    • spring-jdbc

    • spring-orm

    • spring-tx

  • 2)Spring 配置文件配置Druid连接池信息

    <!--加载外部属性文件-->
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <!--数据源-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="${mysql.driverClassName}"/><property name="url" value="${mysql.url}"/><property name="username" value="${mysql.username}"/><property name="password" value="${mysql.password}"/>
    </bean>

    沿用之前章节的Jdbc.properties配置信息,但稍作修改

    mysql.driverClassName=com.mysql.jdbc.Driver
    mysql.url=jdbc:mysql://127.0.0.1:3306/book_db
    mysql.username=root
    mysql.password=sasa
  • 3)配置JdbcTemplate对象,注入dataSource

    <!--配置JdbcTemplate-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><!--属性注入dataSource--><property name="dataSource" ref="dataSource"></property>
    </bean>

2.4 为何使用属性注入?

JdbcTemplate虽然含有DataSource的有参构造,但其调用了setDataSource()方法

这个方法是在其父类中定义了的:

  • 4)创建 Service 和 Dao 类,在 Dao 类中注入JdbcTemplate对象

    <!--Dao 类--> public interface BookDao {
    }
    @Repository
    public class BookDaoImpl implements BookDao {@Autowiredprivate JdbcTemplate jdbcTemplate;
    }
    <!--Service 类-->@Service
    public class BookServiceImpl implements BookService {@Autowiredprivate BookDao bookDao;
    }

    别忘了开启注解扫描

    <!--开启注解扫描-->
    <context:component-scan base-package="com.zking.spring"/>

2.5 配置文件整体结构

<?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">
​<!--开启注解扫描--><context:component-scan base-package="com.zking.spring"/>
​<!--加载外部属性文件--><context:property-placeholder location="classpath:jdbc.properties"/><!--数据源--><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="${mysql.driverClassName}"/><property name="url" value="${mysql.url}"/><property name="username" value="${mysql.username}"/><property name="password" value="${mysql.password}"/></bean><!--配置JdbcTemplate--><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><!--属性注入dataSource--><property name="dataSource" ref="dataSource"></property></bean>
</beans>

3.添加操作

3.1 步骤预览

  • 1)创建数据库中t_book表对应的实体对象

  • 2)编写 Service 和 Dao 代码,增加添加图书的功能逻辑

  • 3)代码测试

3.2 详细操作

  • 1)创建数据库中t_book表对应的实体对象

    public class Book {private Integer id;private String name;private Double price;//省略get/set方法
    }
  • 2)编写 Service 和 Dao 代码,增加添加图书的功能逻辑

Service 类:添加addBook()方法

@Repository
public class BookDaoImpl implements BookDao {@Autowiredprivate JdbcTemplate jdbcTemplate;
​@Overridepublic int save(Book book) {String sql = "insert into t_book(id,name,price) values(null,?,?)";Object[] params = {book.getName(),book.getPrice()};return jdbcTemplate.update(sql,params);}
}

Dao 类:通过操作JdbcTemplate对象的update()方法可实现插入,其中两个参数分别是

  • 第一个参数sql:编写插入数据对应的sql语句,可使用通配符?做占位符

  • 第二个参数args:可变参数列表,设置占位符对应的参数值

@Service
public class BookServiceImpl implements BookService {@Autowiredprivate BookDao bookDao;
​@Overridepublic int save(Book book) {return bookDao.save(book);}
}

  • 3)代码测试

    @Testpublic void testSave(){//操作JdbcTemplate对象,使用update方法进行增删改操作ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");BookService bookService = ctx.getBean("bookServiceImpl",BookService.class);Book book = new Book();book.setName("西游记");book.setPrice(200.0);bookService.save(book);}

    刷新数据库中t_book表数据,核验是否插入成功

    可以看到,表中成功新增了一条数据

4.修改和删除

修改、删除操作和添加操作代码逻辑基本一致

BookService 类:添加updateBook()deleteBook()方法

    /*** 修改*/int update(Book book);/*** 删除*/int delete(Integer id);

BookDao 类:添加update()delete()方法

    /*** 修改*/int update(Book book);/*** 删除*/int delete(Integer id);

BookDaoImpl 类:实现update()delete()方法

@Override
public int update(Book book) {String sql = "update t_book set name=?,price=? where id=?";Object[] params={book.getName(),book.getPrice(),book.getId()};return  jdbcTemplate.update(sql,params);
}
​
@Override
public int delete(Integer id) {String sql = "delete from t_book where id=?";Object[] params={id};return jdbcTemplate.update(sql,params);
}

4.1 测试修改

@Test
public void testUpdate(){ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");BookService bookService = ctx.getBean("bookServiceImpl",BookService.class);Book book = new Book();book.setId(19);book.setName("西游记");book.setPrice(250.0);bookService.update(book);
}

4.2 测试删除

@Test
public void testDelete(){ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");BookService bookService = ctx.getBean("bookServiceImpl",BookService.class);bookService.delete(19);
}

5.查询操作

这里演示三种查询操作:

  • 1)查询返回某个值

  • 2)查询返回对象

  • 3)查询返回集合

为了演示效果,需要先在数据库的t_book表中添加两条数据

接着我们先将代码完成,最后再作进一步的分析说明

5.1 代码实现

BookService 类:添加count()findById()list()方法

@Override
public int count() {return bookDao.count();
}
​
@Override
public Book findById(Integer id) {return bookDao.findById(id);
}
​
@Override
public List<Book> list() {return bookDao.list();
}

BookDao 类:添加selectCount()selectById()selectAll()方法

    /*** 查找返回一个值*/int count();
​/*** 查找返回对象*/Book findById(Integer id);/*** 查找返回集合*/List<Book> list();

BookDaoImpl 类:实现count()findById()list()方法

    @Overridepublic int count() {String sql = "select count(0) from t_book";return jdbcTemplate.queryForObject(sql,Integer.class);}
​@Overridepublic Book findById(Integer id) {String sql = "select * from t_book where id=?";return jdbcTemplate.queryForObject(sql,new BeanPropertyRowMapper<>(Book.class),id);}
​@Overridepublic List<Book> list() {String sql = "select * from t_book";return jdbcTemplate.query(sql,new BeanPropertyRowMapper<>(Book.class));}

测试代码

@Test
public void testQuery(){ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");BookService bookService = ctx.getBean("bookServiceImpl",BookService.class);int count = bookService.count();System.out.println(count);Book book = bookService.findById(1);System.out.println(book);List<Book> list=bookService.list();System.out.println(list);
}

测试结果:

1
Book{id=1, name='西游记', price=200.0}
[Book{id=1, name='西游记', price=200.0}]

5.2 代码分析

上述代码逻辑中使用到了queryForObject()query()方法

jdbcTemplate.queryForObject(sql, Integer.class);
jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(Book.class), id);
jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Book.class));

分别对应JdbcTemplate中的三个方法:

public <T> T queryForObject(String sql, Class<T> requiredType);
public <T> T queryForObject(String sql, RowMapper<T> rowMapper, Object... args);
public <T> List<T> query(String sql, RowMapper<T> rowMapper);

其中,有两个参数值得关注,一个是Class<T> requiredType,另一个是RowMapper<T> rowMapper

  • Class<T> requiredType:返回值的Class类型

  • RowMapper<T> rowMapper:是一个接口,返回不同类型数据,可以使用其实现类进行数据的封装。其实现类有很多,因为我们需要返回一个数据库实体对象,所以可以选择使用BeanPropertyRowMapper

另外,queryForObject(String sql, RowMapper<T> rowMapper, Object... args)query(String sql, RowMapper<T> rowMapper)

区别在于:

  • queryForObject返回一个对象

  • query返回一个集合

6.小结

简单总结下JdbcTemplate操作数据库的各个方法:

  • 添加、修改、删除操作:update()方法

  • 查询操作:queryForObject()query()方法,关注两个参数:

    • Class<T> requiredType:返回值的Class类型

    • RowMapper<T> rowMapper:接口,具体实现类BeanPropertyRowMapper,封装对象实体

  • 批量操作:batchUpdate()方法

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • UE5学习笔记21-武器的射击功能
  • 【小沐学OpenGL】Ubuntu环境下glew的安装和使用
  • 2.10鼠标事件
  • malloc中的mmap是如何分配内存的
  • Leetcode第414周赛第二题:3281. 范围内整数的最大得分
  • 两种常用损失函数:nn.CrossEntropyLoss 与 nn.TripletMarginLoss
  • ​Benvista PhotoZoom Pro 9.0.4新功能介绍
  • 解决 Python IDLE 横向显示文字的方法
  • JavaWeb笔记整理14——公共字段自动填充技术实现
  • 比特币网络和支付
  • Linux网络编程IO管理
  • 使用Docker快速启动Nacos集群
  • 微信小程序页面制作——个人信息
  • 探究:为什么JavaScript要在body标签尾部引入?
  • 韦季李输入法_屏幕键盘第二个选择
  • 「译」Node.js Streams 基础
  • 2019.2.20 c++ 知识梳理
  • - C#编程大幅提高OUTLOOK的邮件搜索能力!
  • CentOS6 编译安装 redis-3.2.3
  • Dubbo 整合 Pinpoint 做分布式服务请求跟踪
  • interface和setter,getter
  • Magento 1.x 中文订单打印乱码
  • PHP的Ev教程三(Periodic watcher)
  • uni-app项目数字滚动
  • 分享自己折腾多时的一套 vue 组件 --we-vue
  • 开发基于以太坊智能合约的DApp
  • 理解 C# 泛型接口中的协变与逆变(抗变)
  • 利用DataURL技术在网页上显示图片
  • 前嗅ForeSpider中数据浏览界面介绍
  • 如何学习JavaEE,项目又该如何做?
  • Prometheus VS InfluxDB
  • 国内开源镜像站点
  • ​一帧图像的Android之旅 :应用的首个绘制请求
  • #162 (Div. 2)
  • (附源码)springboot 基于HTML5的个人网页的网站设计与实现 毕业设计 031623
  • (附源码)ssm跨平台教学系统 毕业设计 280843
  • (转)树状数组
  • ****三次握手和四次挥手
  • .Net Core 生成管理员权限的应用程序
  • .net core 外观者设计模式 实现,多种支付选择
  • .NET DataGridView数据绑定说明
  • .Net MVC + EF搭建学生管理系统
  • .net MVC中使用angularJs刷新页面数据列表
  • .Net Web窗口页属性
  • .NET/C# 反射的的性能数据,以及高性能开发建议(反射获取 Attribute 和反射调用方法)
  • .NET平台开源项目速览(15)文档数据库RavenDB-介绍与初体验
  • .net下简单快捷的数值高低位切换
  • .xml 下拉列表_RecyclerView嵌套recyclerview实现二级下拉列表,包含自定义IOS对话框...
  • @ComponentScan比较
  • @JSONField或@JsonProperty注解使用
  • @Transactional事务注解内含乾坤?
  • @Valid和@NotNull字段校验使用
  • [12] 使用 CUDA 加速排序算法
  • [2024-06]-[大模型]-[Ollama] 0-相关命令
  • [240812] X-CMD 发布 v0.4.5:更新 gtb、cd、chat、hashdir 模块功能