《Spring JDBC 操作数据库》

来源:互联网 发布:百度bae链接数据库 编辑:程序博客网 时间:2024/06/05 01:15

《Spring JDBC 操作数据库》

官方文档链接:http://docs.spring.io/spring/docs/current/spring-framework-reference/html/jdbc.html

1、Spring Framework JDBC 简介

Spring Framework JDBC抽象提供的增值可能通过下表中列出的操作顺序显示出来。 该表显示了Spring将要处理哪些操作,哪些操作是您(应用程序开发人员)的责任。

从上表中可以看到,

Spring框架帮助我们做的事情有:打开数据库连接,执行相关sql语句,处理异常,操作事务,关闭数据库连接

我们仅需要关注:定义数据库连接参数,声明SQL语句,处理每一次得到的结果

即Spring框架负责处理可以使JDBC像这样一个乏味的API开发的所有低级细节。

1.1选择JDBC数据库访问的方法

除了三种风格的JdbcTemplate之外,新的SimpleJdbcInsert和SimplejdbcCall方法优化了数据库元数据,RDBMS对象样式采用了类似于JDO Query设计的面向对象方法。一旦你开始使用这些方法之一,你仍然可以混合和匹配,以包括来自不同方法的功能。所有方法都需要符合JDBC 2.0的驱动程序,一些高级功能需要JDBC 3.0驱动程序。

1)JdbcTemplate

JdbcTemplate是一种经典且最流行的Spring JDBC方法,这是一种最底层(lowest level)的方法,其他方法内部都借助与JdbcTemplate来完成。

2)NamedParameterJdbcTemplate

NamedParameterJdbcTemplate 封装了JdbcTemplate以提供命名参数,而不是传统的JDBC“?”占位符。

3)SimpleJdbcInsert 和 SimpleJdbcCall

SimpleJdbcInsert和SimpleJdbcCall优化数据库元数据,以限制必要配置的数量。

这种方法简化了编码,只需要提供表或过程的名称,并提供与列名匹配的参数映射。这仅在数据库提供足够的元数据时有效。如果数据库不提供此元数据,则必须提供参数的显式配置。

4)RDBMS Objects

RDBMS Objects 包括 MappingSqlQuery, SqlUpdate 和 StoredProcedure,需要你在数据访问层初始化期间建立可重用的并且是线程安全的对象。

此方法在JDO Query之后建模,你可以在其中定义查询字符串,声明参数并编译查询。一旦你这样做,执行方法可以多次调用传入的各种参数值。

1.2 包的层次结构(Package hierarchy)

Spring JDBC 由四个不同的包构成,分别为:core、datasource、object和support,如下图所示。

1)core

即org.springframework.jdbc.core为核心包,它包含了JDBC的核心功能。此包内有很多重要的类,包括:JdbcTemplate类、SimpleJdbcInsert类,SimpleJdbcCall类,以及NamedParameterJdbcTemplate类。

2)datasource

即数据源包,访问数据源的实用工具类。它有多种数据源的实现,可以在JavaEE容器外部测试JDBC代码。

3)object

即对象包,以面向对象的方式访问数据库。它允许执行查询并返回结果作为业务对象。它可以在数据表的列和业务对象的属性之间映射查询结果。

4)support
即支持包,是core包和object包的支持类。例如提供了异常转换功能的SQLException类。

2、使用JDBC核心类JdbcTemplate来控制基本的JDBC处理

2.1 JdbcTemplate

JdbcTemplate这个类位于JDBC core包中。它能够创建和释放资源,这就能帮助我们避免类似于忘记关掉connection这样常见的错误。

它执行核心JDBC工作流的基本任务,例如:创建和执行语句,其中应用程序代码需要提供SQL以及提取结果。

JdbcTemplate这个类执行SQL查询、更新语句和存储工程的调用,在ResultSet上执行迭代并提取返回的参数值。

这个类还捕获JDBC异常以及转换这些异常为org.springframework.dao包中定义的通用,更详细的异常层次结构。

JdbcTemplate可以通过使用DataSource引用的直接实例化在DAO实现中使用,或者在Spring IoC容器中配置,并将其作为bean引用指定给DAO。

注意:DataSource应该始终配置为Spring IoC容器中的一个bean。 在第一种情况下,该bean直接发送给服务器; 在第二种情况下,它被给予准备好的模板。

2.2JdbcTemplate用法实例

下面两个截图为官方文档上所列举的相关用法,比较简单哈,更多可以看官方文档,链接在这里:http://docs.spring.io/spring/docs/current/spring-framework-reference/html/jdbc.html。

3、实践

上面的相关知识基本翻译自官方文档。下面将通过一个完整的项目例子来进行说明。

具体步骤如下:

1、新建一个spring工程,目录结构如下。

2、引入相关依赖,pom.xml文件的完整内容如下。

    <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.wrh</groupId>      <artifactId>springjdbc</artifactId>      <version>1.0-SNAPSHOT</version>      <packaging>jar</packaging>      <name>springjdbc</name>      <url>http://maven.apache.org</url>      <properties>        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>      </properties>      <dependencies>        <dependency>          <groupId>junit</groupId>          <artifactId>junit</artifactId>          <version>3.8.1</version>          <scope>test</scope>        </dependency>        <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->        <dependency>          <groupId>org.springframework</groupId>          <artifactId>spring-jdbc</artifactId>          <version>4.3.8.RELEASE</version>        </dependency>        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->        <dependency>          <groupId>org.springframework</groupId>          <artifactId>spring-context</artifactId>          <version>4.3.7.RELEASE</version>        </dependency>        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->        <dependency>          <groupId>mysql</groupId>          <artifactId>mysql-connector-java</artifactId>          <version>6.0.6</version>        </dependency>      </dependencies>    </project>

3、配置文件:applicationContext.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">        <context:component-scan base-package="com.wrh" />        <bean id="datasource"              class="org.springframework.jdbc.datasource.DriverManagerDataSource" >            <property name="driverClassName" value="com.mysql.jdbc.Driver" />            <!--注意一下&characterEncoding要修改为&amp;characterEncoding-->            <property name="url" value="jdbc:mysql://localhost:3306/dbstudent?useSSL=false"/>            <property name="username" value="root"/>            <property name="password" value="123456" />        </bean>        <!--        <bean id="jdbcTemplate"              class="org.springframework.jdbc.core.JdbcTemplate" abstract="false"              lazy-init="false" autowire="default" >            <property name="dataSource">                <ref bean="datasource" />            </property>        </bean>        <bean id="studentDao"              class="com.wrh.dao.StudentDao">              <property name="jdbcTemplate">                <ref bean="jdbcTemplate" />            </property>        </bean>        -->    </beans>

该文件主要有1个bean,为:DataSource,并开启了组件扫描。注释掉的代码为在该配置文件中声明另外的2个bean:JdbcTemplate和StudentDao。

4、实体类:Student

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

5、DAO层:StudentDao

该类主要是通过JdbcTemplate类来操作数据库,这里是提供了两个查询函数,其他类似于插入/更新类似,具体代码见后面。

    package com.wrh.dao;    import com.wrh.bean.Student;    import org.springframework.beans.factory.annotation.Autowired;    import org.springframework.jdbc.core.JdbcTemplate;    import org.springframework.stereotype.Repository;    import javax.sql.DataSource;    import java.util.ArrayList;    import java.util.Iterator;    import java.util.List;    import java.util.Map;    /**     * @Author:wojiushimogui     * @Description:     * @Date:Created by 下午4:20 on 2017/6/5.     */    @Repository    public class StudentDao {        private JdbcTemplate jdbcTemplate;        @Autowired        public void setDataSource(DataSource dataSource) {            this.jdbcTemplate = new JdbcTemplate(dataSource);        }        public List findALL() {            String sql = "select * from student";            return jdbcTemplate.queryForList(sql);        }        public List<Student> findALLStudent() {            List<Student> studentList = new ArrayList<Student>();;            String sql = "select * from student";            List list = jdbcTemplate.queryForList(sql);//List<Map<String, Object>>            Iterator iterator = list.iterator();            Student student = null;            while (iterator.hasNext()) {                Map map4student = (Map) iterator.next();                student = new Student();                student.setId(((Integer)map4student.get("ID")).intValue());                student.setName((String) map4student.get("NAME"));                student.setAge(((Integer)map4student.get("AGE")).intValue());                studentList.add(student);            }            return studentList;        }    }

6、工具类:SpringUtil

该工具类主要用于根据beanName来获取对象实例。

    /**     * @Author:wojiushimogui     * @Description:     * @Date:Created by 下午4:55 on 2017/6/5.     */    public class SpringUtil {        private static ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");        public static Object getBean(String beanName){            return ctx.getBean(beanName);        }    }

7、主函数类:StudentMain

    public class StudentMain    {        public static void main( String[] args )        {            StudentDao dao = (StudentDao) SpringUtil.getBean("studentDao");            List<Student> studentList = dao.findALLStudent();            for(Student student:studentList){                System.out.println(student.getId()+","+student.getName()+","+student.getAge());            }            System.out.println("---------------------------------");            List list = dao.findALL();            for(Iterator it = list.iterator(); it.hasNext(); ) {                System.out.println(it.next());            }        }    }

如果此时数据库中的student表的数据如上图所示,则运行次程序后的结果如下图所示

其他数据库操作:根据ID来查询以及插入和更新数据

前面我们仅仅是使用了查询语句,并且是查出表中所有的数据,这里我也对其他的操作进行了测试,例如:1)根据Id来查询,2)插入数据,3)更新数据。

由于参考官方文档,因此实现代码相当简单。完整的StudntDao类代码如下:

    package com.wrh.dao;    import com.wrh.bean.Student;    import org.springframework.beans.factory.annotation.Autowired;    import org.springframework.jdbc.core.JdbcTemplate;    import org.springframework.stereotype.Repository;    import javax.sql.DataSource;    import java.util.ArrayList;    import java.util.Iterator;    import java.util.List;    import java.util.Map;    /**     * @Author:wojiushimogui     * @Description:     * @Date:Created by 下午4:20 on 2017/6/5.     */    @Repository    public class StudentDao {        private JdbcTemplate jdbcTemplate;        @Autowired        public void setDataSource(DataSource dataSource) {            this.jdbcTemplate = new JdbcTemplate(dataSource);        }        /**         * 查询表中的所有信息,返回值类型:List<Map<String, Object>>         * */        public List findALL() {            String sql = "select * from student";            return jdbcTemplate.queryForList(sql);        }        /**         * 查询表中的所有信息,返回值类型:List<Student>         * */        public List<Student> findALLStudent() {            List<Student> studentList = new ArrayList<Student>();;            String sql = "select * from student";            List list = jdbcTemplate.queryForList(sql);//List<Map<String, Object>>            Iterator iterator = list.iterator();            Student student = null;            while (iterator.hasNext()) {                Map map4student = (Map) iterator.next();                student = new Student();                student.setId(((Integer)map4student.get("ID")).intValue());                student.setName((String) map4student.get("NAME"));                student.setAge(((Integer)map4student.get("AGE")).intValue());                studentList.add(student);            }            return studentList;        }        /**         * 根据id来查询学生的名字         * */        public String findById(Integer id){            String name = this.jdbcTemplate.queryForObject(                    "select name from student where id = ?",                    new Object[]{id}, String.class);            return name;        }        /**         * 插入一条学生信息         * */        public void insertOneStudent(String name,Integer age){            this.jdbcTemplate.update(                    "insert into student (name, age) values (?, ?)",                    name, age);        }        /**         * 根据指定Id来更新学生的信息         * */        public void updateOneStudentById(Integer id,String name,Integer age){            this.jdbcTemplate.update(                    "update student set name = ?  , age =? where id = ?",                    name, age,id);        }    }

用于测试的StudentMain类中的完整代码如下:

    public class StudentMain    {        public static void main( String[] args )        {            StudentDao dao = (StudentDao) SpringUtil.getBean("studentDao");            List<Student> studentList = dao.findALLStudent();            for(Student student:studentList){                System.out.println(student.getId()+","+student.getName()+","+student.getAge());            }            System.out.println("---------------------------------");            List list = dao.findALL();            for(Iterator it = list.iterator(); it.hasNext(); ) {                System.out.println(it.next());            }            System.out.println("--------------根据ID来查询一个学生的信息-------------------");            Integer id = 13;            String name = dao.findById(id);            System.out.println("id=13所对应的学生名字为:"+name);            System.out.println("-----------插入一个学生信息----------------------");            dao.insertOneStudent("spring jdbc",18);            System.out.println("-----------根据ID来更新一个学生信息----------------------");            dao.updateOneStudentById(13,"updateName",10);        }    }

相关的测试结果截图如下:
其中第一张截图为:根据Id来查询一个学生信息的结果。第二张截图为:插入一个学生信息的结果。第三张截图为:根据Id更新学生信息的结果。

完整工程代码可以在这里获取:https://github.com/wojiushimogui/springjdbc

实践过程中遇到的错误

为便于以后自己查找方便,实践过程中遇到的错误另开了一篇博文,链接:http://blog.csdn.net/u010412719/article/details/72878227

小结

总的来说,关于Spring JDBC的相关操作还是比较简单的,但简单的功劳得归功于Spring,这也是Spring这个伟大框架的强大之处。

其他的关于翻译官方文档,确实挺不好做的,自己有时候知道它在说什么,但是翻译过来就是那么的别扭,感谢google吧,使翻译出来的东西稍微好了一点。

参考资料

1、http://docs.spring.io/spring/docs/current/spring-framework-reference/html/jdbc.html