【修真院Java小课堂】JDBCTemplate和JDBC

本文介绍了JDBC的基础知识,包括其工作原理和数据库操作步骤,然后深入讲解了Spring框架中的JDBCTemplate,作为JDBC的封装,提供了更便捷和安全的数据库操作方式。JDBCTemplate简化了代码,提高了安全性,但需与Spring框架结合使用。文章还探讨了JDBCTemplate与JDBC的优缺点以及PreparedStatement与Statement的区别,并给出使用JDBCTemplate的编码实战示例。

大家好,我是IT修真院成都分院第12期学员,一枚正直善良的java程序员。

今天给大家分享一下,修真院官网java任务一中会使用到的知识点:

JDBCTemplateJDBC

1.    背景介绍

最近在做任务一,按照任务步骤学习了JDBC,以及JDBCTemplate,自己总结了一下两者的相关知识点,对比了两者之间的关系。

2.    知识剖析

2.1什么是JDBC

JDBC, 全称为Java DataBase Connectivity, 它是一个面向对象的应用程序接口(API, 通过它可訪问各类关系数据库。JDBC也是java核心类库的一部分。

JDBC的最大特点是它独立于详细的关系数据库。JDBC API 中定义了一些Java类分别用来表示与数据库的连接(connections, SQL语句(SQL statements, 结果集(resultsets)以及其他的数据库对象, 使得Java程序能方便地与数据库交互并处理所得的结果。使用JDBC, 全部Java程序(包括Java applications , appletsservlet)都能通过SQL语句或存储在数据库中的过程(storedprocedures)来存取数据库。

要通过JDBC来存取某一特定的数据库。必须有对应的JDBC driver。它往往是由生产数据库的厂家提供,是连接JDBC API与详细数据库之间的桥梁。

通常,Java程序首先使用JDBCAPI来与JDBCDriver Manager交互,由JDBC Driver Manager加载指定的JDBC drivers, 以后就能够通过JDBCAPI来存取数据库。

Java程序员在工作中很重要的一点就是得和数据库打交道,但是java代码和数据库是两个不相干的,这个时候就用到JDBC,来使用代码对数据库进行操作。

首先讲JDBC肯定离不开DAODataAccess Object)层,而JDBC的原理就是通过Connection对象获取数据库的连接,然后通过PreparedStatement对象处理SQL语句,再通过它的.setObject方法传入数据,最后通过方法.executeUpdate().executeQuery()执行更新和查询,这就是JDBC的基本原理。

可以看到,JDBC涉及到了连接数据库、然后处理SQL语句、然后传值,最后释放资源这几个过程,可以说任何通过java代码对数据库的操作都离不开这几个过程。

 JDBC访问数据库的步骤

1)得到数据库驱动程序

2)创建数据库连接

3)执行SQL语句

4)得到结果集

5)对结果集做相应的处理(,,,)

6)关闭资源:这里释放的是DB中的资源

2.2什么是JDBC Template

JdbcTemplateSpring框架自带的对JDBC操作的封装,目的是提供统一的模板方法使对数据库的操作更加方便、友好,效率也不错。但是功能还是不够强大(比如不支持级联属性),在实际应用中还需要和hibernatemybaties等框架混合使用。

JDBCTemplate就是SpringJDBC的封装,通俗点说就是Springjdbc的封装的模板,那么JDBCTemplate怎么做到的,这就和spring有关系了

SpringIOC容器将管理数据库连接的数据源当作普通Java Bean一样管理,然后将数据源注入封装类JdbcTemplate,JdbcTemplatedataSource属性就是注入配置的数据源

首先JDBCTemplate是涉及到spring框架的一种方法,JDBCTemplate就是通过.xml配置文件极大的简化了我们代码量,并且提高了安全性。 通过配置文件实现代码简化

其实和JDBC的思路是大同小异的。

首先我们需要在接口实现类中拥有一个set方法,这个是使用JDBCTemplate一定要注意的,没有会报错,而这个set方法就是用来连接数据库的。然后创建DataSource对象和JDBCTemplate对象,分别是用来连接数据库和处理SQL语句的。最后使用JDBCTemplate对象的.update方法和.query方法分别实现插入和查找。

讲完原理,还有配置文件的功用还没讲。

配置文件中的东西不多,一个是DataSource对象的bean,另一个是接口实现类的bean并且和DataSourcebean做了引用。最后在测试类中(就是驱动函数中),我们需要用ApplicationContext对象存储配置文件的路径,该路径通过ClassPathXmlApplicationContext得到,

然后用ApplicationContext对象的.getBean方法连接到配置文件里的接口实现类的bean,然后就使用方法了.

可以看到JDBCTemplate其实对JDBC的获取数据库连接的Connection对象做了封装,提高了整体安全性,并且减少了大量冗余代码,提高工作效率;插入、删除等操作时也不用像JDBC一个一个字段进行操作了,极大简化代码量,减少失误;并且摒弃了TryCatch块,更加安全了。

2.3三种种方式得到JDBCTemplate对象

要使用JDBCTemplate对象来完成JDBC操作。通常情况下,有三种种方式得到JDBCTemplate对象。

1)我们可以在自己定义的DAO 实现类中注入一个DataSource引用来完JdbcTemplate 的实例化。也就是它是从外部“注入”DataSource DAO 中,然后自己实例化JdbcTemplate,然后将DataSource设置到JdbcTemplate对象中。

2)在 Spring IoC 容器中配置一个JdbcTemplate bean,将 DataSource 注入进来,然后再把JdbcTemplate 注入到自定义DAO 中。

3Spring 提供了org.springframework.jdbc.core.support.JdbcDaoSupport JdbcTemplate 属性,也定义了DataSource属性,当设置DataSource属性的时候,会创jdbcTemplate的实例,所以我们自己编写的DAO 只需要继承JdbcDaoSupport类,然后注入DataSource 即可

2.4JdbcTemplate类主要提供以下几类方法:

1execute方法:用于执行任何SQL语句,一般用于执行DDL语句;

2update方法及batchUpdate方法:update方法用于执行新增、修改、删除等语句,batchUpdate方法用于执行批处理相关语句;

3query方法及queryForXXX方法:用于执行查询相关语句;

3.    常见问题

3.1 JDBCTemplate和JDBC的优缺点

3.2 PreparedStatement和Statement有什么区别?

4.    解决方案

4.1 JDBCTemplate和JDBC的优缺点

 JDBC

优点:运行期:快捷、高效

缺点:编辑器:代码量大、繁琐异常处理、不支持数据库跨平台

JDBCTemplate

优点:运行期:高效、内嵌Spring框架中、支持基于AOP的声明式事务

缺点:必须于Spring框架结合在一起使用、不支持数据库跨平台、默认没有缓存

4.2 PreparedStatement和Statement有什么区别

Statement每次执行SQL语句,相关数据库都要进行SQL语句编译,PreparedStatement是预编译,对批量处理大大提高效率,可以防止SQL注入攻击,防止数据库缓冲池溢出,代码的可读性,可维护性都更好

5.    编码实战

 下面是使用JDBCTemplate的一个例子

5.1定义一个简单类Student,并定义它的三个属性age、name、id,并定义好各属性的set与get方法,方便以后调用

package com.example;
/*
定义一个简单类Student,并定义它的三个属性age、name、id,并定义好各属性的set与get方法,方便以后调用
*/

public class Student {
private Integer age;
   private String name;
   private Integer id;
   public void setAge(Integer age) {
this.age = age;
   }
public Integer getAge() {
return age;
   }
public void setName(String name) {
this.name = name;
   }
public String getName() {
return name;
   }
public void setId(Integer id) {
this.id = id;
   }
public Integer getId() {
return id;
   }
}

5.2定义接口StudentDAO,并创建后面需要使用的方法

package com.example;

import javax.sql.DataSource;
import java.util.List;
/*
定义接口StudentDAO,并创建后面需要使用的方法
*/
public interface StudentDAO {
public void setDataSource(DataSource ds);//这个方法用于连接数据库,并完成初始化
   public void create(String name,Integer age);//这个方法用于录入数据
   public Student getStudent(Integer id);//这个方法用于获得表中对应id的记录
   public List<Student> listStudents();//这个方法用于列出表中所有记录
   public void delete(Integer id);//这个方法用于删除表中对应id的记录
   public void update(Integer idInteger age);//这个方法用于更新表中的记录
}

5.3建立Student的映射器StudentMapper,它用于实现RowMapper接口,RowMapper接口用来把数据库中的列字段和java bean中属性对应上,以方便赋值

package com.example;

import org.springframework.jdbc.core.RowMapper;

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

/*
建立Student的映射器StudentMapper,它用于实现RowMapper接口,RowMapper接口用来把数据库中的列字段和java bean中属性对应上,
以方便赋值
*/

public class StudentMapper implements RowMapper<Student> {
public Student mapRow(ResultSet rs, int rowNum) throws SQLException {
//实例化Student对象student,以便调用Student类下个属性的set方法来给各属性赋值
       Student student = new Student();
       student.setId(rs.getInt("id"));
       student.setName(rs.getString("name"));
       student.setAge(rs.getInt("age"));
       //返回student对象
       return student;
   }
}

5.4定义一个实现类StudentJDBCTemplate来实现前面定义的StudentDAO接口

package com.example;

import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;
import java.util.List;
/*

定义一个实现类StudentJDBCTemplate来实现前面定义的StudentDAO接口
*/

public class StudentJDBCTemplate implements StudentDAO {
//定义了 StudentJDBCTemplate类的一个属性dataSource
   private DataSource dataSource;
   //定义了 StudentJDBCTemplate类的一个属性jdbcTemplateObject
   private JdbcTemplate jdbcTemplateObject;
   //定义了属性dataSource的set方法,并初始化属性dataSource的值为dataSource
   public void setDataSource(DataSource dataSource){
this.dataSource = dataSource;
     // 实例化了JdbcTemplate类的一个带参数(dataSource)的对象,并将让jdbcTemplateObject指向此对象
       //必须传入对应参数才能调用此有参构造创建的对象
       this.jdbcTemplateObject new JdbcTemplate(dataSource);
   }

public void create(String nameInteger age) {
String SQL = "insert into Student (name, age) values (?, ?)";
       jdbcTemplateObject.update( SQLnameage);
       System.out.println("Created Record Name = " + name + " Age = " + age);
       return;
   }
public Student getStudent(Integer id) {
String SQL = "select * from Student where id = ?";
       Student student = jdbcTemplateObject.queryForObject(SQL,
               new Object[]{id}, new StudentMapper());
       return student;
   }
public List<Student> listStudents() {
String SQL = "select * from Student";
       List <Student> students = jdbcTemplateObject.query(SQL,
               new StudentMapper());
       return students;
   }
public void delete(Integer id){
String SQL = "delete from Student where id = ?";
       jdbcTemplateObject.update(SQLid);
       System.out.println("Deleted Record with ID = " + id );
       return;
   }
public void update(Integer idInteger age){
String SQL = "update Student set age = ? where id = ?";
       jdbcTemplateObject.update(SQLageid);
       System.out.println("Updated Record with ID = " + id );
       return;
   }
}

5.5测试类:

public class MainApp {
public static void main(String[] args) {
//1.创建spring的IOC容器对象context,并加载配置文件
       ApplicationContext context =
new ClassPathXmlApplicationContext("Beans.xml");
       //2.从IOC容器中获取Bean实例
       StudentJDBCTemplate studentJDBCTemplate =
(StudentJDBCTemplate)context.getBean("studentJDBCTemplate");
       //3.调用对象的方法
       //录入数据
       System.out.println("------Records Creation--------" );
       studentJDBCTemplate.create("小明"22);
       studentJDBCTemplate.create("刘备"45);
       studentJDBCTemplate.create("赵云"26);
       //查询记录并将结果保存在结果集中
       System.out.println("------Listing Multiple Records--------" );
       List<Student> students = studentJDBCTemplate.listStudents();
       for (Student record : students) {
System.out.print("ID : " + record.getId() );
           System.out.print(", Name : " + record.getName() );
           System.out.println(", Age : " + record.getAge());
       }
//更新记录并将结果保存在结果集中
       System.out.println("----Updating Record with ID = 2 -----" );
       studentJDBCTemplate.update(220);
       System.out.println("----Listing Record with ID = 2 -----" );
       Student student = studentJDBCTemplate.getStudent(2);
       System.out.print("ID : " + student.getId() );
       System.out.print(", Name : " + student.getName() );
       System.out.println(", Age : " + student.getAge());
   }
}

5.6bean.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 初始化数据来源 -->
    <bean id="dataSource"
          class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/my_db"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>

    <!-- 定义StudentJDBCTemplate的bean -->
    <bean id="studentJDBCTemplate"
          class="com.example.StudentJDBCTemplate">
        <property name="dataSource"  ref="dataSource" />
    </bean>


</beans>

6.    扩展思考

mybatis与jdbc、JDBCTemplate三者有什么区别?

MyBatis也是对JDBC的封装,MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装。MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(普通的Java对象)映射成数据库中的记录。

使用mapper代理的方法来开发dao

1.编写mapper.xml映射文件

2.编写mapper接口(相当于dao接口).不需要写具体实现类,只需要写接口即可,但是接口不能直接使用

7.    参考文献

https://blog.youkuaiyun.com/u011305680/article/details/60879953

https://www.cnblogs.com/love-Stefanie/p/6838269.html

https://blog.youkuaiyun.com/u014282557/article/details/76761403

https://www.cnblogs.com/tuhooo/p/6491913.html

https://blog.youkuaiyun.com/lxlmycsdnfree/article/details/73287396

https://blog.youkuaiyun.com/qq_32671287/article/details/70212584 

8.    更多讨论

(1)使用 jdbc.properties配置文件有什么好处?

假如我们需要更改连接数据库的配置,我们直接在jdbc.properties里面更改一次就可以了,提高了工作效率,减少了重复代码,适应不同的数据库连接,而JDBC的话需要增删改查里面每个连接数据库的配置都需要更改。

(2)如果发生数据库连接资源被占用,有什么解决方法

修改 MySQL 安装目录下 my.ini 或者 my.cnf 文件内的max_user_connections 参数的数值,重启 MySQL 服务器。

(3)jdbctemplate和mybatis分别在什么情况下使用,jdbc template  和spring+mybatis一样吗?,和mybatis相比有什么优缺点?

这三个问题其实差不多,JDBCTemplate和Mybatis不一样,Mybatis的sql语句放在了mapper.xml文件里面.相当于配置在了环境当中,随时都可以使用. 而JDBCTemplate则是写在了实现类里面,使用的时候还要进行重新调用配置之类的. 以后的工作中可能对多个表进行操作,配置在环境中使用起来非常方便.

(4)如何来控制数据库的打开关闭.

Class.forName("com.mysql.jdbc.Driver");这个初始化驱动就是打开了数据库链接

Connectionc = DriverManager.//连接数据库,

//关闭数据链接

ps.close();

c.close();

而JDBCTemplate的打开关闭则是封装在JDBCTemplate当中。

(5)jdbc 和 jdbctemplate 相比  效率有差别么

单从效率方面来说,实际上jdbc比jdbctemplate的效率会高一点.jdbcTemplate则更方便我们进行更改内容,和理解当中的逻辑。

(6)jdbcTemplate 实现执行多条sql语句。

一种直接用mysql的批量处理语句.

另外一种拼接SQL语句直接一次性提交多少条数据

(7)jdbcTemplate有什么缺点。

必须于Spring框架结合在一起使用、不支持数据库跨平台、默认没有缓存。

(8)连接池

1).当有多个线程,每个线程都需要连接数据库执行SQL语句的话,那么每个线程都会创建一个连接,并且在使用完毕后,关闭连接。创建连接和关闭连接的过程也是比较消耗时间的,当多线程并发的时候,系统就会变得很卡顿。同时,一个数据库同时支持的连接总数也是有限的,如果多线程并发量很大,那么数据库连接的总数就会被消耗光,后续线程发起的数据库连接就会失败。

2.).连接池在使用之前,就会创建好一定数量的连接。 如果有任何线程需要使用连接,那么就从连接池里面借用,而不是自己重新创建. 使用完毕后,又把这个连接归还给连接池供下一次或者其他线程使用。倘若发生多线程并发情况,连接池里的连接被借用光了,那么其他线程就会临时等待,直到有连接被归还回来,再继续使用。整个过程,这些连接都不会被关闭,而是不断的被循环使用,从而节约了启动和关闭连接的时间。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值