④JdbcTemplate与声明式事务

JdbcTemplate

1.概述

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

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

总结一下:

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

2.准备工作

2.1 相关SQL

javascript 复制代码
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连接池信息

    javascript 复制代码
    <!--加载外部属性文件-->
    <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配置信息,但稍作修改

    javascript 复制代码
    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

    javascript 复制代码
    <!--配置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对象

    javascript 复制代码
    <!--Dao 类--> 
    
    public interface BookDao {
    }
    @Repository
    public class BookDaoImpl implements BookDao {
        @Autowired
        private JdbcTemplate jdbcTemplate;
    }
    <!--Service 类-->
    
    @Service
    public class BookServiceImpl implements BookService {
        @Autowired
        private BookDao bookDao;
    }

    别忘了开启注解扫描

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

2.5 配置文件整体结构

javascript 复制代码
<?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表对应的实体对象

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

Service 类:添加addBook()方法

javascript 复制代码
@Repository
public class BookDaoImpl implements BookDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;
​
    @Override
    public 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:可变参数列表,设置占位符对应的参数值

javascript 复制代码
@Service
public class BookServiceImpl implements BookService {
    @Autowired
    private BookDao bookDao;
​
    @Override
    public int save(Book book) {
        return bookDao.save(book);
    }
}
  • 3)代码测试

    javascript 复制代码
    @Test
        public 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()方法

javascript 复制代码
    /**
     * 修改
     */
    int update(Book book);
    /**
     * 删除
     */
    int delete(Integer id);

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

javascript 复制代码
    /**
     * 修改
     */
    int update(Book book);
    /**
     * 删除
     */
    int delete(Integer id);

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

javascript 复制代码
@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 测试修改

javascript 复制代码
@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 测试删除

javascript 复制代码
@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()方法

javascript 复制代码
@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()方法

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

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

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

测试代码

javascript 复制代码
@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);
}

测试结果:

javascript 复制代码
1
Book{id=1, name='西游记', price=200.0}
[Book{id=1, name='西游记', price=200.0}]

5.2 代码分析

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

javascript 复制代码
jdbcTemplate.queryForObject(sql, Integer.class);
jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(Book.class), id);
jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Book.class));

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

javascript 复制代码
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()方法

相关推荐
.生产的驴1 分钟前
SpringBoot 消息队列RabbitMQ死信交换机
java·spring boot·后端·rabbitmq·java-rabbitmq
星迹日11 分钟前
C语言:结构体
c语言·开发语言·经验分享·笔记
会敲代码的小张23 分钟前
设计模式-观察者模式
java·开发语言·后端·观察者模式·设计模式·代理模式
哲伦贼稳妥3 小时前
网络运维故障处理
运维·网络·经验分享·职场和发展
Flying_Fish_roe5 小时前
Spring Boot-Bean注入问题
spring boot·后端·log4j
开 端5 小时前
文件批量添加水印和密码合并单元格完整版
java·ide·spring
.生产的驴6 小时前
SpringBoot 消息队列RabbitMQ 消息可靠性 数据持久化 与 LazyQueue
java·spring boot·后端·eclipse·rabbitmq·maven·java-rabbitmq
计算机学姐7 小时前
基于python+django+vue的二手电子设备交易平台
开发语言·vue.js·后端·python·mysql·django·web3.py
蔚一8 小时前
Java设计模式—面向对象设计原则(四) ----->接口隔离原则(ISP) (完整详解,附有代码+案例)
java·后端·设计模式·intellij-idea·接口隔离原则
qq_172805599 小时前
GO Govaluate
开发语言·后端·golang·go