我们在之前学习过JDBC和Mybatis访问数据库,但是在JDBC中访问数据库我们可以发现代码量hi非常的大,下面我们将JDBC、Mybatis和我们的Spring JDBC进行对比,看看它们有什么区别.
1.异常体系:在JDBC中我们的异常是检查异常,也就是说这个异常如果我们不处理程序就无法运行,其次在JDBC中我们的异常就只有一个SQLException,这样的话我们在进行数据库访问的时候如果出现了异常,这个信息将不是明确的定位我们并不知道具体出错的地方。但是我们的SpringJDBC对于以后长的处理就比较细化,下面通过例子来看:
(1)配置pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.wschase</groupId>
<artifactId>springcorelianxi-repository-case</artifactId>
<version>1.0.0</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>7</source>
<target>7</target>
</configuration>
</plugin>
</plugins>
</build>
<!--这是一个Springcore的案例:我们需要添加Spring的物料清单-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>4.3.9.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!--Spring框架依赖-->
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<!--Spring的JDBC模块-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<!--alibaba的数据库连接池(数据源):是为了管理数据库连接的-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.13</version>
</dependency>
<!--添加驱动:驱动是为了连接数据库的-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.43</version>
</dependency>
</dependencies>
</project>
(2)配置文件
1)application.properties
jdbc.url=jdbc:mysql://localhost:3306/library
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.username=root
jdbc.password=1041646364
2)application-context.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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--注意:一般我们在application-context里面我们就配置公共的、总的,这样在文件里面也体现出三层架构-->
<!--
选择一个最优的方式,自己写的类通过注解的方式声明并且自动装配,所以我们
开启扫描,通过注解方式声明bean和自动装配
-->
<context:component-scan base-package="com.wschase.springcore"/>
<!--配置文件-->
<context:property-placeholder location="application.properties"/>
<!--导入数据库连接池的配置-->
<import resource="application-jdbc.xml"/>
</beans>
3)application-jdbc.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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--
因为:阿里的这个数据库连接池一个第三方的,第三方的话我们没有办法通过注解自动给它注入一个Bean,
所以我们只能通过一个配置文件;
数据源的配置:它的名字就叫dataSource
-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<!--注意::这些属性在我们的程序部署的时候也是会发生变化的,所以我们将它配置到文件里面去,通过${}的形式进行引用-->
<!--属性配置:对于一个数据源来说最终的属性就是driverClassName-->
<property name="driverClassName" value="${jdbc.driverClass}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<!--
连接池的连接配置
-->
<!--(1)初始化配置-->
<property name="initialSize" value="10"/>
<!--(2)最大活动-->
<property name="maxActive" value="20"/>
<!--(3)最小连接数-->
<property name="minIdle" value="10"/>
<!--(3)查询超时时间,单位是s-->
<property name="queryTimeout" value="5"/>
</bean>
<!--<!–第二个数据源的Bean–>-->
<!--<bean id="managerDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">-->
<!--<property name="driverClassName" value="${jdbc.driverClass}"/>-->
<!--<property name="url" value="${jdbc.url}"/>-->
<!--<property name="username" value="${jdbc.username}"/>-->
<!--<property name="password" value="${jdbc.password}"/>-->
<!--</bean>-->
<!--使用Spring JDBC Template的一个模板:因为这个不是我们自己实现的所以我们需要通过添加配置文件将它导入-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--需要获取一个数据源连接数据库-->
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
(3)代码编写
属性类:
package com.wschase.springcore.jdbctemplate;
/**
* Author:WSChase
* Created:2019/5/2
*/
public class Book {
private String name;
private String author;
private String isbn;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getIsbn() {
return isbn;
}
public void setIsbn(String isbn) {
this.isbn = isbn;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", author='" + author + '\'' +
", isbn='" + isbn + '\'' +
'}';
}
}
1)传统JDBC的实现
package com.wschase.springcore.jdbc;
import org.springframework.stereotype.Component;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
* Author:WSChase
* Created:2019/5/2
*/
@Component//通过注解的方式将我们的这个dataSource注解到数据源里面去
public class JdbcOperation {
private final DataSource dataSource;
public JdbcOperation(DataSource dataSource) {
this.dataSource = dataSource;
}
/**
* 功能实现
*/
//1.添加一本书
public void addBook(){
Connection connection=null;
PreparedStatement statement=null;
try {
//(1)获取连接
connection= dataSource.getConnection();
//(2)创建命令
statement=connection.prepareStatement("insert into soft_bookrack(book_name,book_author,book_isbn) values (?,?,?)");
//(3)赋值参数
statement.setString(1,"剑指");
statement.setString(2,"张明");
statement.setString(3,"31993853");
//(4)执行命令
int effect=statement.executeUpdate();
System.out.println("Execute Result "+effect);
} catch (SQLException e) {
e.printStackTrace();
}finally {
if(statement!=null){
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(connection!=null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
//2.更新
public void updateBook(){
Connection connection=null;
PreparedStatement statement=null;
try {
//(1)获取连接
connection= dataSource.getConnection();
//(2)创建命令:从这个地方可以看出我们到底有几个参数
statement=connection.prepareStatement("update soft_bookrack set book_author=? where book_isbn=?");
//(3)赋值参数
statement.setString(1,"张伟并");
statement.setString(2,"31993853");
//(4)执行命令
int effect=statement.executeUpdate();
System.out.println("Execute Result "+effect);
} catch (SQLException e) {
e.printStackTrace();
}finally {
if(statement!=null){
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(connection!=null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
//3.查询一本书
public void queryBook(){
Connection connection=null;
PreparedStatement statement=null;
ResultSet resultSet=null;
try {
//(1)获取连接
connection= dataSource.getConnection();
//(2)创建命令
statement=connection.prepareStatement("select book_name,book_author,book_isbn from soft_bookrack where book_isbn=?");
//(3)赋值参数
statement.setString(1,"31993853");
//(4)执行命令
resultSet=statement.executeQuery();
List<Book> bookList=new ArrayList<>();
//取到这个结果
while (resultSet.next()){
Book book=new Book();
book.setName(resultSet.getString("book_name"));
book.setName(resultSet.getString("book_author"));
book.setName(resultSet.getString("book_isbn"));
//将我们取得的结果放到我们的集合里面
//bookList.add(book);
}
System.out.println(bookList);
} catch (SQLException e) {
e.printStackTrace();
}finally {
//释放资源
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(statement!=null){
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(connection!=null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
package com.wschase.springcore.jdbc;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Author:WSChase
* Created:2019/5/2
*/
public class JdbcApplication {
public static void main(String[] args) {
//获取容器
ApplicationContext context=new ClassPathXmlApplicationContext("application-context.xml");
//因为我们只有一个类所以可以直接通过Class获取实例对象
JdbcOperation jdbcOperation= context.getBean(JdbcOperation.class);
jdbcOperation.addBook();
jdbcOperation.updateBook();
jdbcOperation.queryBook();
}
}
2)SpringJDBC的实现
package com.wschase.springcore.jdbctemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Component;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
/**虽然采用Jdbc Template的方法进行数据库的访问变得简单的许多,代码量少了许多,但是还是存在一个问题就是并没有处理事务
* Author:WSChase
* Created:2019/5/3
*/
@Component
public class JdbcTemplateOperation {
@Autowired
private JdbcTemplate jdbcTemplate;
public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
/**
* 功能实现:通过JDBC Template来实现
*/
//1.添加一本书:
// 我们可以明显的看到代码量变少了,因为这个更新方法在我们的Jdbc Template里面就有我们直接使用就可以了;
//不需要获取连接、建立命令等等步骤。其次在这种情况下我们并没有捕获异常,但是在方法名上我们还是有异常的
//只是他是运行时异常我们可以不用捕获。
public void addBook(){
int effect = this.jdbcTemplate.update(
"insert into soft_bookrack(book_name,book_author,book_isbn) values (?,?,?)",
"Spring in Action",
"耿一",
"828143005"
);
System.out.println("Add book result"+ effect);
}
//2.更新
public void updateBook(){
int effect = this.jdbcTemplate.update(
"update soft_bookrack set book_author=? where book_isbn=?",
"张伟",
"828143002"
);
System.out.println("Update book result"+ effect);
}
//3.查询一本书
//3.1
public void queryBook(){
//直接将我们的结果封装成了一个对象
List<Map<String,Object>> bookList=this.jdbcTemplate.queryForList(
"select book_name,book_author,book_isbn from soft_bookrack where book_isbn=?",
"828143002"
);
System.out.println(bookList);
}
//3.2:返回一个对象
public void queryBookForObject(){
//直接将我们的结果封装成了一个对象
List<Book> bookList=this.jdbcTemplate.query(
"select book_name,book_author,book_isbn from soft_bookrack where book_isbn=?",
new Object[]{"828143002"},
//这个参数表示行映射:映射成为一个Book对象
new RowMapper<Book>() {
@Override
public Book mapRow(ResultSet resultSet, int i) throws SQLException {
Book book=new Book();
book.setName(resultSet.getString("book_name"));
book.setAuthor(resultSet.getString("book_author"));
book.setIsbn(resultSet.getString("book_isbn"));
return book;
}
}
);
System.out.println(bookList);
}
//3.2查询数量
public int queryCount(){
int count=this.jdbcTemplate.queryForObject(
"select count(book_isbn) from soft_bookrack",
//这个是需要返回的类型
Integer.class
);
System.out.println("Count Book"+ count);
return count;
}
// //3.3按照条件查询:错误的用法,queryForObject主要用在返回值是单列单行
// public Book queryBookByIsbn(){
// Book book=this.jdbcTemplate.queryForObject(
// "select book_name,book_isbn from soft_bookrack where book_isbn=?",
// new Object[]{"828143002"},
// //这个是需要返回的类型
// Book.class
// );
// System.out.println("queryBookByIsbn Book"+ book);
// return book;
// }
//4.删除一本书
public void deleteBook(){
int effect=this.jdbcTemplate.update(
"delete from soft_bookrack where book_isbn=?",
"828143002"
);
System.out.println("Delete book result"+ effect);
}
}
package com.wschase.springcore;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import javax.sql.DataSource;
/**
* Author:WSChase
* Created:2019/5/2
*/
public class DataSourceApplicaion {
public static void main(String[] args) {
//取得容器
ApplicationContext context=new ClassPathXmlApplicationContext("application-context.xml");
//通过容器取得对象实例化:这个时候有两个数据源不可以直接通过类来获取,要么通过名字获取、要么注掉一个数据源
DataSource dataSource=context.getBean(DataSource.class);
//看看这个到底是哪个类
System.out.println(dataSource.getClass().getCanonicalName());
}
}
package com.wschase.springcore.jdbctemplate;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
/**这个是我们的JdbcTemplate实现数据库的访问
* Author:WSChase
* Created:2019/5/2
*/
public class SpringJdbcApplication {
public static void main(String[] args) {
//获取容器
ApplicationContext context=new ClassPathXmlApplicationContext("application-context.xml");
JdbcTemplateOperation jdbcTemplate=context.getBean(JdbcTemplateOperation.class);
//jdbcTemplate.addBook();
jdbcTemplate.updateBook();
jdbcTemplate.queryBook();
jdbcTemplate.queryBookForObject();
jdbcTemplate.queryCount();
//jdbcTemplate.queryBookByIsbn();
jdbcTemplate.deleteBook();
}
}
可以很明显看出来它们在异常处理、代码量上面都有很大的差别,这是因为SpringJDBC里面有一个JdbcTemplate这个模板类,可以让我们实现减少那些准备工作,只需要实现我们数据库的CRUD功能就可以了。此外,还有一个特别大的不同之处:我们的SpringJDBC支持我们的事务,但是传统的JDBC并不支持,我们在进行数据库的操作的时候很难保证不会出错,而且一般是一组的sql语句,也就是我们一般都是对数据库进行书屋的操作,事务的操作我们就会出现错误,所以我们需要回滚、提交等事务,这个功能可以通过我们的SpringCore里面的数据库事务实现。这就是我们SpringJDBC的优点。