猿人进化系列12——一文快速学会数据库访问姿势

看完上一个章节,相信你已经掌握了MYSQL数据库的基本操作,以及SQL的基本写法,可是你只会用图形化工具编写和执行SQL,而在实际的程序开发中,你是需要用程序来操作数据库的,今天我们就来学习下JAVA访问数据库的姿势。

     猿进化是一个原创系列文章,帮助你从一只小白快速进化为一个猿人,更多精彩内容,敬请大家关注公主号猿人工厂,点击猿人养成获取

之前我们学习了数据库的基本操作,JAVA的基本语法和一些常用的API。学习web开发,需要从数据库里动态的获取数据,需要现在我们来学习使用JAVA相关的知识来访问数据库。


 

 

JAVA通过什么来访问数据库呢?常规套路是使用JDBC来访问。JDBC是JAVAEE定义的数据库访问规范,它定义了数据库访问接口,具体的实现由各个数据库厂商去完成。JDBC仅仅是定义了接口,但是要操作数据库,还需要实现类去完成,也就是数据库驱动去完成。每个厂商都会去完成各自的数据库驱动实现,比如我们使用的MYSQL数据库,它的数据库厂商,也就是oracle,会去提供数据库驱动。使用JAVA操作数据库,我们只要会调用JDBC的方法就可以了。

看到没?这就是规范的发展套路,你不实现我就不支持你访问,你要卖数据库,要想有人用你的数据库你必须要有驱动,要不然没人用。ODBC为啥渐渐的被人忘记,因为大家支持了SUN,不过对于猿人来说也是有好处的:

1.咱们只用关心接口就好,屏蔽了个厂商之间数据库通信的细节

2.面向接口编程(想想面向对象思想那一章,用接口的好处了吧,多态呀多态无处不在),编写一套代码,用较小的修改(是不可能滴,SQL方言不一样哒)就能访问其他支持JDBC的数据库。

 

使用JDBC访问数据库的步骤如下:

1. 引入数据库驱动相关的jar包

 在pom.xml中增加

 <!--mysql驱动-->

        <dependency>

            <groupId>mysql</groupId>

            <artifactId>mysql-connector-java</artifactId>

            <version>5.1.26</version>

            <scope>compile</scope>

        </dependency>

(maven自动帮我们下载)

2. 注册驱动

3. 创建数据库连接(Connection)

4. 定义sql

5. 创建执行sql语句的对象 PreparedStatement

6.设置PreparedStatement的参数

7. 执行sql,接受返回结果

8. 处理数据库返回结果 ResultSet

9. 释放资源

 

根据ID查询学生记录:

public class JDBCCRUDDemo {

    private static void queryStudentById(Long id) throws SQLException{
        Connection connection = null;
        ResultSet rs = null;
        PreparedStatement ps=null;
        try{
            //1)注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            //2) 得到连接对象
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test01","root","123456");
            //sql无需区分大小写
            String sql="select * from student where ID = ?";
            //3) 得到语句对象
            ps = connection.prepareStatement(sql);
            //4)设置参数,parameterIndex 注意:index从1开始算起 1代表第一个参数,即第一个问号
            ps.setLong(1,id);
            //5) 执行SQL语句得到结果集ResultSet对象
            rs = ps.executeQuery();
            //6) 循环遍历取出每一条记录
            while(rs.next()) {
                Long dbId = rs.getLong("id");
                String name = rs.getString("name");
                int sex = rs.getInt("sex");
                Date birthday = rs.getDate("admission_date");
                String remark = rs.getString("remark");
                //7) 输出的控制台上
                System.out.println("编号:" + dbId + ", 姓名:" + name + ", 性别:" + sex + ", 入学日期:" + birthday+",备注:"+remark);
            }
        }catch(Exception e){
            e.printStackTrace();
        }
        finally{
            //8) 释放资源       一定要牢记
            if(null!=rs){
                rs.close();
            }
            if(null!=ps){
                ps.close();
            }
            if(null!=connection){
                connection.close();
            }

        }

    }

    public static void main(String args[]){

        try {
            queryStudentById(2L);
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
     }
    }

新增学生记录:

private static void addStudent(String name,int sex,Date admissionDate,String remark ) throws SQLException{
    Connection connection = null;
    int rows = 0;
    PreparedStatement ps=null;
    try{
        //1)注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2) 得到连接对象
        connection =
                DriverManager.getConnection("jdbc:mysql://localhost:3306/test01?characterEncoding=utf8","root","123456");
        //sql无需区分大小写
        String sql="insert into  student(name,sex,admission_date,remark) values(?,?,?,?)";
        //3) 得到语句对象
        ps = connection.prepareStatement(sql);
        //4)设置参数,parameterIndex 注意:index从1开始算起 1代表第一个参数,即第一个问号
        ps.setString(1,name);
        ps.setInt(2,sex);

        ps.setDate(3,new java.sql.Date(admissionDate.getTime()));
        ps.setString(4,remark);
        //5) 执行SQL语句得到结果集ResultSet对象
        rows = ps.executeUpdate();
        //6) 循环遍历取出每一条记录
        //7) 输出的控制台上
        System.out.println("插入记录条数:" +rows);
    }catch(Exception e){
        e.printStackTrace();
    }
    finally{
        //8) 释放资源       一定要牢记
        if(null!=ps){
            ps.close();
        }
        if(null!=connection){
            connection.close();
        }

    }

}

 

按ID修改学生记录:

private static void updateStudent(String name,int sex,Date admissionDate,String remark,Long id ) throws SQLException{
    Connection connection = null;
    int rows = 0;
    PreparedStatement ps=null;
    try{
        //1)注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2) 得到连接对象
        connection =
                DriverManager.getConnection("jdbc:mysql://localhost:3306/test01?characterEncoding=utf8","root","123456");
        //sql无需区分大小写
        String sql="update   student set name=?, sex=? ,admission_date=? ,remark =? where id=?";
        //3) 得到语句对象
        ps = connection.prepareStatement(sql);
        //4)设置参数,parameterIndex 注意:index从1开始算起 1代表第一个参数,即第一个问号
        ps.setString(1,name);
        ps.setInt(2,sex);

        ps.setDate(3,new java.sql.Date(admissionDate.getTime()));
        ps.setString(4,remark);
        ps.setLong(5, id);
        //5) 执行SQL语句得到结果集ResultSet对象
        rows = ps.executeUpdate();
        //6) 循环遍历取出每一条记录
        //7) 输出的控制台上
        System.out.println("修改记录条数:" +rows);
    }catch(Exception e){
        e.printStackTrace();
    }
    finally{
        //8) 释放资源       一定要牢记
        if(null!=ps){
            ps.close();
        }
        if(null!=connection){
            connection.close();
        }

    }

}

按ID删除学生记录:

private static void deleteStudent(Long id ) throws SQLException{
    Connection connection = null;
    int rows = 0;
    PreparedStatement ps=null;
    try{
        //1)注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2) 得到连接对象
        connection =
                DriverManager.getConnection("jdbc:mysql://localhost:3306/test01?characterEncoding=utf8","root","123456");
        //sql无需区分大小写
        String sql="delete from student where id=?";
        //3) 得到语句对象
        ps = connection.prepareStatement(sql);
        //4)设置参数,parameterIndex 注意:index从1开始算起 1代表第一个参数,即第一个问号

        ps.setLong(1, id);
        //5) 执行SQL语句得到结果集ResultSet对象
        rows = ps.executeUpdate();
        //6) 循环遍历取出每一条记录
        //7) 输出的控制台上
        System.out.println("删除记录条数:" +rows);
    }catch(Exception e){
        e.printStackTrace();
    }
    finally{
        //8) 释放资源       一定要牢记
        if(null!=ps){
            ps.close();
        }
        if(null!=connection){
            connection.close();
        }

    }

}

什么是数据库连接池?数据库连接池是存放数据库连接的容器,当容器被创建后,会向数据库申请数据库连接资源。我们从数据库连接池里获取数据库连接使用完毕后,会将连接还给容器。好处:

连接池复用了数据库连接,减少了访问数据库时,创建连接的开销,提高了程序的访问效率。

数据库连接池原理:

实现javax.sql包下的DataSource接口

获取数据库连接使用:

获取连接:getConnection()

归还连接:Connection.close()注意,使用数据库连接,不会关闭连接,而是归还。

一般来说,我们不用自己去实现数据库连接池,有很多很成熟的第三方产品可以使用。这里推荐阿里巴巴开源的Druid。

接下来我们看看怎么来使用它:

1.引入jar包

在pom.xml文件中增加

<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>druid</artifactId>
  <version>1.0.9</version>
</dependency>

2.定义配置文件

在src/main/resources下新建文件druid.properties

在文件中增加内容

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/test01?characterEncoding=utf8
username=root
password=123456
initialSize=5
maxActive=10
maxWait=3000

 

说明:

driverClassName驱动名称 MYSQL 使用com.mysql.jdbc.Driver

url数据库访问url

username数据库用户名

password数据库密码

initialSize 初始化连接数

maxActive  最大活动连接数

maxWait    数据库访问超时时间 毫秒

我们再简单地封装数据库访问工具类:

 

package com.pz.web.demo.Util;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class JDBCUtils {
    // 1.  声明静态数据源成员变量
    private static DataSource dataSource;

    // 2. 创建连接池对象
    static {
        // 加载配置文件中的数据
        InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");
        Properties pp = new Properties();
        try {
            pp.load(is);
            // 创建连接池,使用配置文件中的参数
            dataSource = DruidDataSourceFactory.createDataSource(pp);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 3. 定义公有的得到数据源的方法
    public static DataSource getDataSource() {
        return dataSource;
    }

    // 4. 定义得到连接对象的方法
    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }

    // 5.定义关闭资源的方法
    public static void close(Connection conn, Statement stmt, ResultSet rs) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {}
        }

        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException e) {}
        }

        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {}
        }
    }

    // 6.重载关闭方法
    public static void close(Connection conn, Statement stmt) {
        close(conn, stmt, null);
    }
}

 

Spring JDBC 是Spring框架对jdbc的模板封装,能够简化数据访问的开发,支持使用对象访问数据库。

我们看看使用Spring JDBC 访问数据库的步骤:

1.引入依赖

  <dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-core</artifactId>
  <version>4.1.2.RELEASE</version>
  <scope>compile</scope>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-jdbc</artifactId>
  <version>4.1.2.RELEASE</version>
</dependency>

2.创建JdbcTemplate对象

 

3.使用JdbcTemplate提供的相关方法,访问数据库。JdbcTemplate支持以对象的方式访问数据库,数据库里的一条记录是唯一的,对象也是唯一的,我们可以简单的把数据库里的字段名,看作是domain类的属性名,数据库里的一行记录,看作是一个domain类的一个实例。

由于JdbcTemplate支持对象和查询结果集字段的小驼峰匹配或者是完全匹配,建议domain类命名遵循和数据库字段的小驼峰匹配规则(首字母小写如果遇到下划线,则每一个下划线后第一个字母大写)。

我们看到student表的字段如下:

 

所以我们定义的domian类如下:

package com.pz.web.demo.domain;

import java.util.Date;

/**
 *
 * @author pangzi
 * 字段名和数据库字段命名规则
 * 由于JdbcTemplate支持对象和查询结果集字段的小驼峰匹配或者是完全匹配,
 * 建议domain类命名遵循和数据库字段的小驼峰匹配规则
 *
 */
public class Student {
    /**
     * id编号
     */
    private Long id;
    /**
     * 姓名
     */
    private String name;
    /**
     * 性别
     */
    private int sex ;

    /**
     * 年龄
     */
    private int age ;

    /**
     * 入学日期
     */
    private Date admissionDate;
    /**
     * 备注
     */
    private String remark;

    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getSex() {
        return sex;
    }
    public void setSex(int sex) {
        this.sex = sex;
    }
    public Date getAdmissionDate() {
        return admissionDate;
    }
    public void setAdmissionDate(Date admissionDate) {
        this.admissionDate = admissionDate;
    }
    public String getRemark() {
        return remark;
    }
    public void setRemark(String remark) {
        this.remark = remark;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Student [id=" + id + ", name=" + name + ", sex=" + sex
                + ", age=" + age + ", admissionDate=" + admissionDate
                + ", remark=" + remark + "]";
    }

}

 

JdbcTemplate提供的数据访问方法如下:

queryForObject:将查询结果封装为对象,注意查询结果只能有一条记录,如果无查询结果返回,程序可能异常

queryForList():将查询结果封装为List集合。

update();用于执行dml语句,增删改。

queryForMap():查询结果将结果集封装为map集合,将列名作为key,将值作为value,注意查询结果只能有一条记录

 

package com.pz.web.demo.jdbc;

import com.pz.web.demo.Util.JDBCUtils;
import com.pz.web.demo.domain.Student;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;

import java.sql.SQLException;
import java.util.Date;
import java.util.List;

/**
 *
 * @author pangzi
 *
 */
public class SpringJDBCCRUDDemo {

    private static JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());

    /**
     * 按id查询学生信息
     * @param id
     * @return
     * @throws SQLException
     */
    private static Student queryStudentById(Long id) throws SQLException{

        Student student = null;
        try {
            String sql = " select * from student where ID = ?";
            student = template.queryForObject(sql, new BeanPropertyRowMapper<Student>(Student.class), id);
        } catch (DataAccessException e) {
            e.printStackTrace();
        }
        return student;


    }

    /**
     * 查询所有学生记录
     * @return
     * @throws SQLException
     */
    private static List<Student> queryStudentList() throws SQLException{

        String sql = " select * from student ";
        return template.query(sql,new BeanPropertyRowMapper<Student>(Student.class));

    }

    /**
     * 新增学生记录
     * @param student
     * @throws SQLException
     */
    private static void addStudent(Student student ) throws SQLException{

        String sql="insert into  student(name,sex,age,admission_date,remark) values(?,?,?,?,?)";
        template.update(sql,student.getName(),student.getSex(),student.getAge(),student.getAdmissionDate(),student.getRemark()
        );

    }

    /**
     * 修改学生记录
     * @param student
     * @throws SQLException
     */
    private static void updateStudent(Student student) throws SQLException{

        String sql="update   student set name=?, sex=? ,admission_date=? ,remark =? where id=?";
        template.update(sql,student.getName(),
                student.getSex(),
                student.getAdmissionDate()
                ,student.getRemark(),
                student.getId()
        );


    }

    /**
     * 按id删除学生记录
     * @param id
     * @throws SQLException
     */
    private static void deleteStudent(Long id ) throws SQLException{

        String sql="delete from student where id=?";

        template.update(sql,id
        );
    }

    public static void main(String args[]){

        try {
            Student dbStundent=queryStudentById(2L);
            System.out.println(dbStundent);
            Student stundent = new Student();
            stundent.setName("新来的");
            stundent.setSex(1);
            stundent.setAge(18);
            stundent.setRemark("我用JDBCTemplate报名");
            stundent.setAdmissionDate(new Date());
            addStudent(stundent);
            dbStundent.setName("我怎么变成新来的了");
            updateStudent(dbStundent);
            deleteStudent(8L);
            List<Student> allStundents=queryStudentList();
            System.out.println("==所有学生记录==");
            for(Student s:allStundents){
                System.out.println(s);
            }

        } catch (SQLException e) {
           e.printStackTrace();
        }

    }

}

 

注意:JdbcTemplate所有方法支持的都是可变参数,参数个数是不固定的,每一个参数的传入顺序对应sql里的问号。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值