当前位置: 首页 > 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()方法


http://www.mrgr.cn/news/22112.html

相关文章:

  • MATLAB绘图基础6:MATLAB绘图基础
  • 仕考网:2025年公务员国考备考技巧
  • FastAPI数据模型:使用FormData extra参数防止数据污染
  • Python——将原来的gt.txt文件存为gt_原始.txt,修改后的文件作为 gt.txt
  • 基于Java+SpringBoot+Vue+MySQL的西安旅游管理系统网站
  • 828华为云征文|华为云Flexus云服务器X实例之openEuler系统下部署GitLab服务器
  • 开题报告中的研究方法设计:AI能帮你做什么?
  • 【Linux】进程控制(一)
  • 攻防世界--->你好,CTF
  • 使用协程实现高并发的I/O处理
  • 怎么仿同款小程序的开发制作方法介绍
  • RedNet 复现记录
  • 【进程间通信】System V--消息队列和信号量
  • 还不会剪音乐?试试这四款在线音频剪辑
  • JVM - GC垃圾回收
  • 【docker】通过云服务器安转Docker
  • 2024年土建施工员考试题库及答案
  • SprinBoot+Vue公交智能化系统的设计与实现
  • SwiftUI 中如何花样玩转 SF Symbols 符号动画和过渡特效
  • 【基础算法总结】滑动窗口