Spring 坑路4 -> JDBC 的基本操作

本文介绍如何使用SpringJDBC简化传统的JDBC数据库操作,包括批量插入和查询数据的示例代码,展示如何减少代码冗余,提高开发效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JDBC 简介

JDBC(Java Data Base Connectivity,Java 数据库连接)是一种用于执行 SQL 语句的JavaAPI,可以为多种关系数据库提供统一访问,它由一组用 Java 语言编写的类和接口组成。JDBC 为数据库开发人员提供了一个标准的 API,据此可以构建更高级的工具和接口,使数据库开发人员能够用纯 JavaAPI 编写数据库应用程序,并且可跨平台运行,且不收数据库供应商的限制。(在 JDBC 出来之前,是使用 ODBC-JDBC 桥去连接数据库,连接慢、资源浪费。)

JDBC 使用流程:

1.在开发环境中加载指定数据库的驱动程序
2.在 Java 程序中加载驱动程序
3.创造数据库连接对象
4.创建用于执行 SQL 并接收结果的 Statement 对象
5.通过 Statement 对象的特定方法执行 SQL,并得到结果
6.关闭数据库连接

JDBC的问题

1.数据库异常问题
2.每次调用数据库连接,都需要重复地打开数据库连接,过度的代码冗余
3.频繁的数据库连接,形成过度的资源浪费,影响程序性能
4.SQL 太死板,不易动态修改 SQL,也不利于系统的拓展性与维护性
5.结果的封装也比较死板

SpringJDBC 简介

  Spring 中的 JDBC 连接与直接使用JDBC去连接有一定的差别,Spring 对 JDBC 做了大量封装,消除了冗余代码,使得开发量大大减小。
  我们可能都处理过数据库访问功能,在实际的工作中也发现数据库访问有一些不足之处。我们必须初始化数据访问框架、打开连接、处理异常和关闭连接。如果上述操作出现任何问题,都有可能损坏或删除数据。
  Spring 自带了一组数据访问框架,集成了多种数据访问技术,不管是直接通过 JDBC 还是像 Hibernate 这样的对象关系映射(Object-Relational-Mapping,ORM)框架实现数据库持久化,Spring 都能够帮你消除持久化代码中那些单调枯燥的数据访问逻辑。我们可以依赖 Spring 来处理底层的数据访问,以便于专注应用程序中数据的管理。

SpringJDBC 驱动配置:

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/dbname?useSSL=true"></property>
<property name="username" value="username"></property>
<property name="password" value="password"></property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>

JDBCTemplate用法:

execute:可用于执行任何 SQL 语句,一般用于执行 DDL 语句
update:用于执行新增、修改、删除等语句
query:用于执行查询语句
call:用于执行存储过程、函数相关语句

先呈现我 pom.xml 和 目录结构
这里写图片描述
这里写图片描述
数据库中的数据:
这里写图片描述
数据库表结构:
这里写图片描述
在 Spring-Jdbc 之前,增删改查的方式:

springConfig.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-4.2.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-4.2.xsd
    ">
    <context:component-scan base-package="jdbc"/>
</beans>
<?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-4.2.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-4.2.xsd
    ">
    <context:component-scan base-package="jdbc"/>
</beans>

SpringVO 代码内容:

package jdbc;

public class SpringVO {
    private long springId;
    private String springName;
    private String springVersion;
    public long getSpringId() {
        return springId;
    }
    public void setSpringId(long springId) {
        this.springId = springId;
    }
    public String getSpringName() {
        return springName;
    }
    public void setSpringName(String springName) {
        this.springName = springName;
    }
    public String getSpringVersion() {
        return springVersion;
    }
    public void setSpringVersion(String springVersion) {
        this.springVersion = springVersion;
    }
    @Override
    public String toString() {
        return "SpringVO [springId=" + springId + ", springName=" + springName + ", springVersion=" + springVersion
                + "]";
    }
    public SpringVO(long springId, String springName, String springVersion) {
        super();
        this.springId = springId;
        this.springName = springName;
        this.springVersion = springVersion;
    }
    public SpringVO() {
        super();
    }
}

SpringDao 代码内容:

package jdbc;

import java.util.List;

public interface SpringDao {
    int insertSpring();

    List<SpringVO> listSpring();

}

SpringService 代码内容:(SpringService 此处只是打印出了查询后得到的数据)

package jdbc;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class SpringService {
    @Autowired
    private SpringDao springDao;

    public void insertSpring() {
        int ret = springDao.insertSpring();
        System.out.println("batch " + ret + "datas");
    }

    public void listSpring() {
        List<SpringVO> list = springDao.listSpring();
        for (SpringVO springVo : list) {
            System.out.println(springVo);
        }
    }
}

SpringDaoImpl 代码内容:

package jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Component;

@Component
public class SpringDaoImpl implements SpringDao {

    public int insertSpring() {
        Connection conn = null;
        PreparedStatement stmt = null;
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/spring_jdbc?useSSL=true&serverTimezone=UTC",
                    "root", "root");
            stmt = conn
                    .prepareStatement("insert into spring_text(spring_name,spring_version)values('SpringIOC','3.0')");
            int row = stmt.executeUpdate();
            System.out.println("execute row:" + row);
            return row;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            if (stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        return 0;
    }

    public List<SpringVO> listSpring() {
        Connection conn = null;
        PreparedStatement stmt = null;
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/spring_jdbc?useSSL=true&serverTimezone=UTC",
                    "root", "root");
            stmt = conn.prepareStatement("select * from spring_text");
            ResultSet rs = stmt.executeQuery();
            List<SpringVO> list = new ArrayList<>();
            while (rs.next()) {
                list.add(new SpringVO(rs.getInt(1), rs.getString(2), rs.getString(3)));
            }
            return list;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            if (stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }
}

SpringTest 代码内容:

package jdbc;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringTest {
    public static void main(String[] args) {
        AbstractApplicationContext context = new ClassPathXmlApplicationContext("/jdbc/springConfig.xml");
        SpringService springService = (SpringService) context.getBean("springService");
        springService.listSpring();
    }
}

执行结果:

SpringVO [springId=1, springName=SpringIOC, springVersion=3.0]
SpringVO [springId=2, springName=SpringAOP, springVersion=3.5]
SpringVO [springId=3, springName=SpringJDBC, springVersion=3.8]
SpringVO [springId=4, springName=SpringTX, springVersion=4.2]

会发现,单单只是查询和插入的操作,就会占用大量的代码,并且在处理查询和插入的时候,除了业务逻辑,还需要处理错误。这显然是不合理的,如果有大量的查询语句,就会造成代码的严重冗余。

现在使用 SpringJdbc 的方式来消除这些问题。

其中 SpringDao,SpringService,SpringVO,SpringTest中的代码并没有任何改变:

springConfig 代码如下:

<?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-4.2.xsd
    http://www.springframework.org/schema/context  
    http://www.springframework.org/schema/context/spring-context-4.2.xsd">
    <context:component-scan base-package="springjdbc" />
    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url"
            value="jdbc:mysql://localhost:3306/spring_jdbc?useSSL=true&amp;serverTimezone=UTC"></property>
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>
    </bean>
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
</beans>

SpringMapper 代码如下:(SpringMapper 实现了 RowMapper 接口)

package springjdbc;

import java.sql.ResultSet;
import java.sql.SQLException;

import org.springframework.jdbc.core.RowMapper;

public class SpringMapper implements RowMapper<SpringVO> {

    public SpringVO mapRow(ResultSet rs, int rowNum) throws SQLException {
        SpringVO springVo = new SpringVO();
        springVo.setSpringId(rs.getInt("spring_id"));
        springVo.setSpringName(rs.getString("spring_name"));
        springVo.setSpringVersion(rs.getString("spring_version"));
        return springVo;
    }

}

重点来了,SpringDaoImol 中的代码如下:

package springjdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

import springjdbc.impl.SpringDao;

@Component
public class SpringDaoImpl implements SpringDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    public int insertSpring() {
        String sql = "insert into spring_text(spring_name,spring_version)values(?,?)";
        List<Object[]> batchArgs = new ArrayList<>();
        batchArgs.add(new Object[] { "SpringAOP2", "4.4" });
        batchArgs.add(new Object[] { "SpringAOP3", "4.4" });
        int[] rows = jdbcTemplate.batchUpdate(sql, batchArgs);
        List<Integer> primes = IntStream.of(rows).boxed().collect(Collectors.toList());
        int sum = primes.stream().mapToInt(x -> x).sum();
        // IntSummaryStatistics stats = primes.stream().mapToInt(x
        // ->x).summaryStatistics();
        // int sum = (int) stats.getSum();
        // System.out.println(sum);
        return sum;
    }

    public List<SpringVO> listSpring() {
        String sql = "select * from spring_text";
        List<SpringVO> list = jdbcTemplate.query(sql, new SpringMapper());
        return list;
    }
}

运行结果:

SpringVO [springId=1, springName=SpringIOC, springVersion=3.0]
SpringVO [springId=2, springName=SpringAOP, springVersion=3.5]
SpringVO [springId=3, springName=SpringJDBC, springVersion=3.8]
SpringVO [springId=4, springName=SpringTX, springVersion=4.2]

  使用样板式语法,短短的几行代码,就得到了想要的结果,并且不需要关注连接池的开启与关闭以及其他繁琐的点,专心业务逻辑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值