0x00 参考 本笔记直接参考或引自如下链接文章:
https://www.w3cschool.cn/wkspring/
http://c.biancheng.net/spring/
0x01 JDBC框架概述 在使用普通的JDBC数据库时,就会很麻烦的写不必要的代码来处理异常,打开和关闭数据库连接等。但Spring JDBC框架负责所有的低层细节,从开始打开连接,准备和执行SQL语句,处理异常,处理事务,到最后关闭连接。
所以当从数据库中获取数据时,你所做的是定义连接参数,指定要执行的SQL语句,每次迭代完成所需的工作。
Spring JDBC提供几种方法和数据库中相应的不同的类与接口。我将给出使用JdbcTemplate类框架的经典和最受欢迎的方法。这是管理所有数据库通信和异常处理的中央框架类。
0x02 JdbcTemplate类 Spring框架提供的JDBC支持主要由四个包组成,分别是core(核心包)、object(对象包)、dataSource(数据源包)和support(支持包),org.springframework.jdbc.core.JdbcTemplate类就包含在核心包中。作为Spring JDBC的核心,JdbcTemplate类中包含了所有数据库操作的基本方法。
JdbcTemplate类执行SQL查询、更新语句和存储过程调用,执行迭代结果集和提取返回参数值。它也捕获JDBC异常并转换它们到org.springframework.dao包中定义的通用类、更多的信息、异常层次结构。
JdbcTemplate类继承自抽象类JdbcAccessor,同时实现了JdbcOperations接口。其直接父类JdbcAccessor为子类提供了一些访问数据库时使用的公共属性:
DataSource:其主要功能是获取数据库连接,具体实现时还可以引入对数据库连接的缓冲池和分布式事务的支持,它可以作为访问数据库资源的标准接口;
SQLExceptionTranslator:org.springframework.jdbc.support.SQLExceptionTranslator接口负责对SQLException进行转译工作。通过必要的设置或者获取SQLExceptionTranslator中的方法,可以使 JdbcTemplate在需要处理SQLException时,委托SQLExceptionTranslator的实现类完成相关的转译工作;
使用JdbcTemplate类时常见的做法是在你的Spring配置文件中配置数据源,然后共享数据源bean依赖注入到DAO类中,并在数据源的设值函数中创建了JdbcTemplate。
0x03 JDBC配置 配置模板如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 <?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/spring" /> <property name ="username" value ="root" /> <property name ="password" value ="root" /> </bean > <bean id ="jdbcTemplate" class ="org.springframework.jdbc.core.jdbcTemplate" > <property name ="dataSource" ref ="dataSource" /> </bean > <bean id ="xxx" class ="xxx" > <property name ="jdbcTemplate" ref ="jdbcTemplate" /> </bean > ... </beans >
在上述代码中,定义了三个Bean,分别是dataSource、jdbcTemplate和需要注入类的Bean。其中dataSource对应的是DriverManagerDataSource类,用于对数据源进行配置;jdbcTemplate对应JdbcTemplate类,该类中定义了JdbcTemplate的相关配置。
在定义jdbcTemplate时,需要将dataSource注入jdbcTemplate中。而在其他的类中要使用jdbcTemplate,也需要将jdbcTemplate注入使用类中(通常注入dao类中)。
在dataSource中定义了四个连接数据库的属性:
属性名
含义
driverClassName
所使用的驱动名称,对应驱动 JAR 包中的 Driver 类
url
数据源所在地址
username
访问数据库的用户名
password
访问数据库的密码
0x04 JDBC框架使用 数据访问对象(DAO) DAO(Data Access Object)数据访问对象是一个面向对象的数据库接口。DAO类都是进行数据操作的类,是对于数据库中的数据做增删改查等操作的代码。
在Spring中,数据访问对象(DAO)支持很容易用统一的方法使用数据访问技术,如JDBC、Hibernate、JPA或者JDO。
执行SQL语句 我们看看如何使用SQL和jdbcTemplate对象在数据库表中执行CRUD(创建、读取、更新和删除)操作。
查询一个整数类型:
1 2 String SQL = "select count(*) from Student" ; int rowCount = jdbcTemplateObject.queryForInt( SQL );
查询一个 long 类型:
1 2 String SQL = "select count(*) from Student" ; long rowCount = jdbcTemplateObject.queryForLong( SQL );
一个使用绑定变量的简单查询:
1 2 String SQL = "select age from Student where id = ?" ; int age = jdbcTemplateObject.queryForInt(SQL, new Object[]{10 });
查询字符串:
1 2 String SQL = "select name from Student where id = ?" ; String name = jdbcTemplateObject.queryForObject(SQL, new Object[]{10 }, String.class);
查询并返回一个对象:
1 2 3 4 5 6 7 8 9 10 11 12 String SQL = "select * from Student where id = ?" ; Student student = jdbcTemplateObject.queryForObject(SQL, new Object[]{10 }, new StudentMapper()); public class StudentMapper implements RowMapper <Student > { public Student mapRow (ResultSet rs, int rowNum) throws SQLException { Student student = new Student(); student.setID(rs.getInt("id" )); student.setName(rs.getString("name" )); student.setAge(rs.getInt("age" )); return student; } }
查询并返回多个对象:
1 2 3 4 5 6 7 8 9 10 11 12 String SQL = "select * from Student" ; List<Student> students = jdbcTemplateObject.query(SQL, new StudentMapper()); public class StudentMapper implements RowMapper <Student > { public Student mapRow (ResultSet rs, int rowNum) throws SQLException { Student student = new Student(); student.setID(rs.getInt("id" )); student.setName(rs.getString("name" )); student.setAge(rs.getInt("age" )); return student; } }
在表中插入一行:
1 2 String SQL = "insert into Student (name, age) values (?, ?)" ; jdbcTemplateObject.update( SQL, new Object[]{"Zara" , 11 } );
更新表中的一行:
1 2 String SQL = "update Student set name = ? where id = ?" ; jdbcTemplateObject.update( SQL, new Object[]{"Zara" , 10 } );
从表中删除一行:
1 2 String SQL = "delete Student where id = ?" ; jdbcTemplateObject.update( SQL, new Object[]{20 } );
执行DDL语句 DDL是数据定义语言的缩写,简单来说,就是对数据库内部的对象进行创建、删除、修改的操作语言。它和DML语言的最大区别是DML只是对表内部数据的操作,而不涉及到表的定义、结构的修改,更不会涉及到其他对象。DDL语句更多的是被数据库管理员(DBA)所使用,一般的开发人员很少使用。
你可以使用jdbcTemplate中的execute(..)方法来执行任何SQL语句或DDL语句。下面是一个使用CREATE语句创建一个表的示例:
1 2 3 4 5 6 String SQL = "CREATE TABLE Student( " + "ID INT NOT NULL AUTO_INCREMENT, " + "NAME VARCHAR(20) NOT NULL, " + "AGE INT NOT NULL, " + "PRIMARY KEY (ID));" jdbcTemplateObject.execute( SQL );
Demo StudentDAO.java,数据访问对象接口:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 package com.mi1k7ea;import javax.sql.DataSource;import java.util.List;public interface StudentDAO { public void setDataSource (DataSource ds) ; public void create (String name, Integer age) ; public Student getStudent (Integer id) ; public List<Student> listStudents () ; public void delete (Integer id) ; public void update (Integer id, Integer age) ; }
Student.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 package com.mi1k7ea;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; } }
StudentMapper.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package com.mi1k7ea;import org.springframework.jdbc.core.RowMapper;import java.sql.ResultSet;import java.sql.SQLException;public class StudentMapper implements RowMapper <Student > { public Student mapRow (ResultSet rs, int rowNum) throws SQLException { Student student = new Student(); student.setId(rs.getInt("id" )); student.setName(rs.getString("name" )); student.setAge(rs.getInt("age" )); return student; } }
StudentJDBCTemplate.java,定义的DAO接口StudentDAO的实现类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 package com.mi1k7ea;import org.springframework.jdbc.core.JdbcTemplate;import javax.sql.DataSource;import java.util.List;public class StudentJDBCTemplate implements StudentDAO { private DataSource dataSource; private JdbcTemplate jdbcTemplateObject; public void setDataSource (DataSource dataSource) { this .dataSource = dataSource; this .jdbcTemplateObject = new JdbcTemplate(dataSource); } public void create (String name, Integer age) { String SQL = "insert into Student (name, age) values (?, ?)" ; jdbcTemplateObject.update( SQL, name, age); 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(SQL, id); System.out.println("Deleted Record with ID = " + id ); return ; } public void update (Integer id, Integer age) { String SQL = "update Student set age = ? where id = ?" ; jdbcTemplateObject.update(SQL, age, id); System.out.println("Updated Record with ID = " + id ); return ; } }
MainApp.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 package com.mi1k7ea;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import java.util.List;public class MainApp { public static void main (String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml" ); StudentJDBCTemplate studentJDBCTemplate = (StudentJDBCTemplate)context.getBean("studentJDBCTemplate" ); System.out.println("------Records Creation--------" ); studentJDBCTemplate.create("Zara" , 11 ); studentJDBCTemplate.create("Nuha" , 2 ); studentJDBCTemplate.create("Ayan" , 15 ); 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(2 , 20 ); 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()); } }
Beans.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <?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-3.0.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/test?serverTimezone=UTC" /> <property name ="username" value ="root" /> <property name ="password" value ="" /> </bean > <bean id ="studentJDBCTemplate" class ="com.mi1k7ea.StudentJDBCTemplate" > <property name ="dataSource" ref ="dataSource" /> </bean > </beans >
注意,在jdbc协议设置URL时,添加了参数serverTimezone值为UTC进行服务端Timezone的设置,否则会报如下错误:
1 Exception in thread "main" org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.
在执行之前,需要在数据库中执行以下SQL语句创建test数据库以及新建:
1 2 3 4 5 6 7 8 CREATE DATABASE test ;USE test ;CREATE TABLE Student( ID INT NOT NULL AUTO_INCREMENT, NAME VARCHAR (20 ) NOT NULL , AGE INT NOT NULL , PRIMARY KEY (ID ) );
创建成功后,运行MainApp成功使用JDBC框架实现数据库的连接使用:
查看数据库,数据被成功插入: