JDBC——Java连接关系型数据库

JDBC(Java Data Base Connection) java数据库连接 是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一的访问,是由一组Java语言编写的类和接口,JDBC提供了一种基准,以此可以构建更高级的工具和接口。

之前我们简单讲了数据库的一些知识,我们利用驱动程序简介管理数据库。就是因为我们安装好数据库后,我们的应用程序也是不能直接使用数据库的,必须通过响应的数据库驱动程序,通过驱动程序去和数据库打交道,其实也就是数据库的厂商的JDBC接口的实现。

在这里插入图片描述

今天我们简单说一下,Java连接数据库的一些步骤。

首先加载mysql驱动
这里边的路径是固定的,是由mysql厂家提供的驱动去找接口。

Class.forName("com.mysql.jdbc.Driver");

有了驱动,找接口。
加载connection接口
getConnection后三个参数:

  • 连接字符串 :jdbc:mysql://(ip地址/localhost本机):(数据库端口号)/数据库名称
  • 数据库账号
  • 数据库密码
Connection  connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/myschool","root","root");

整体代码如下,连接成功就会输出:连接成功。然后我们再去查询、更新数据。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
//连接数据库
public class Demo1 {
    public static void main(String[] args) {
        Connection connection = null;
        try {
            //加载mysql驱动
            Class.forName("com.mysql.jdbc.Driver");
            //加载connection接口  getConnection(连接字符串,数据库账号,数据库密码);
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/myschool","root","root");
            System.out.println("连接成功");
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                //关闭连接
                if (null != connection)
                    connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

注意:连接数据库操作完,要关闭连接!!!
这里有个问题,我们要导入的jar包,需要自己下载,javav本身不提供。
mysql-connector-java-5.1.0-bin.jar,就是mysql提供的jar包,网上很多,自己找找。

然后我们来操作数据。

通过Connection 的 createStatement()方法 获取Statement接口

   Statement  statement = connection.createStatement();

定义SQL 语句

 String sql = "UPDATE student SET Phone = '15229975743' WHERE StudentNo = '1010'";

statement接口的executeUpdate()方法传入操作语句,返回影响成功的行数

  int row = statement.executeUpdate(sql);

具体代码如下:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

//执行修改语句,返回成功影响行数
public class Demo3 {
    public static void main(String[] args) {
        Connection connection = null;
        Statement statement = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/myschool","root","root");
            System.out.println("连接成功");

            statement = connection.createStatement();
            String sql = "UPDATE student SET Phone = '15229975743' WHERE StudentNo = '1010'";
            int row = statement.executeUpdate(sql);
            System.out.println(row != 0?"修改成功":"修改失败");

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (statement != null){
                    statement.close();
                }
                if (connection != null ){
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

    }
}

注意: 还是一样的,用完即关。而且是正着用倒着关,这很好理解。

然后是查询语句,查询语句不一样的是用的statement接口的executeQuery()方法,照样传入查询语句,但是返回的是一个结果集合ResultSet。

ResultSet rs = statement.executeQuery(sql);

这个集合同样的在最后用完要关掉。

这里我们说一下,查询和更新是都要传入sql语句,而有的人会利用这个去注入恶意代码,常见的sql注入,使得躲避掉数据库操作权限限制。
最简单的举个例子,我们要求用户名密码都一致,才能查询自己的成绩,sql语句:

select * from student WHERE studentUser = '李四' AND loginPwd = '123456789'

我并不知道李四的密码,甚至不知道李四的用户名,那我要查询这个数据库的信息,怎么办,我想了个办法,输入这个句子:

select * from student WHERE studentUser = '' or 1=1 -- 'AND loginPwd = ''

我们可以看到,我利用(’ or 1=1 – )构造了一个1=1的永真条件,后边直接被注释掉,那数据库那边收到这样的语句条件判断肯定为真,那我前边要查的肯定也可以查到。

那么,mysql厂商肯定也注意到这种情况,所以为connection接口提供了prepareStatement()方法。

之前我们要先利用connection接口的createStatement()方法获取statement接口,然后定义sql语句,在查询或者更新数据时用statement接口的executeQuery(sql)或executeUpdate(sql)方法去传入sql语句,进行操作,有被sql注入的风险。

现在我们利用connection接口的prepareStatement()方法去获取preparedStatement接口,它和statement接口有相同的功能,但是会预编译,而且prepareStatement()方法强制先传入sql语句进行预编译。

String sql = "select * from student WHERE studentNo = ? AND loginPwd = ?";
PreparedStatement  preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1,"1010");
preparedStatement.setString(2,"123456");

这里我们传入的sql语句中先不传值,而是用英文的?代替,叫做占位符,
在下边用preparedStatement的(set+数据类型)方法去给占位符赋值,先说明第几个占位符,再写值为多少。
他就会利用预编译将几个值分别去验证,而不是将整个语句打包去执行。

import java.sql.*;
//利用 prepareStatement获取Statement可以预编译,防止sql注入
public class Demo4 {
    public static void main(String[] args) {
        Connection connection = null;
        PreparedStatement  preparedStatement = null;
        ResultSet resultSet = null;

        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/myschool","root","root");
            System.out.println("连接成功");

            String sql = "select * from student WHERE studentNo = ? AND loginPwd = ?";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1,"1010");
            preparedStatement.setString(2,"123456");

            resultSet = preparedStatement.executeQuery();
            while (resultSet.next()){
                System.out.println(resultSet.getInt("studentno")+"---"+resultSet.getString("studentname"));

            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (resultSet != null){
                    resultSet.close();
                }
                if (preparedStatement != null){
                    preparedStatement.close();
                }
                if (connection != null){
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

    }

上面我们讲了用java连接mysql数据库后进行查询、更新数据的方法,但是用着不是很方便,而且我们Java讲究数据作为对象去使用。我们只是查到数据、更新数据,而没有把它弄成一个对象去操作他,没什么意义。所以,我写了下面的工具类,可以查数据、更新数据、把数据封装为一个类,然后去操作他。


import org.apache.commons.beanutils.BeanUtils;
import java.lang.reflect.InvocationTargetException;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class BaseDao {
    private static Connection connection = null;
    private static PreparedStatement preparedStatement = null;
    private static ResultSet resultSet = null;

    static {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    public static void getConnection() throws SQLException {
        connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/myschool", "root", "root");
    }

    public static int executeUpdate(Object[] objects, String sql) {
        int row = 0;
        try {
            getConnection();
            connection.setAutoCommit(false);
            preparedStatement = connection.prepareStatement(sql);

            if (objects != null) {
                for (int i = 0; i < objects.length; i++) {
                    preparedStatement.setObject(i + 1, objects[i]);
                }
            }
            row = preparedStatement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
            try {
                connection.rollback();
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
        } finally {
            try {
                connection.commit();
                connection.setAutoCommit(true);
            } catch (SQLException e) {
                e.printStackTrace();
            }
            closeAll();
        }
        return row;
    }

    public  static ResultSet executeQuery(Object[] objects,String sql){
        try {
            getConnection();
            preparedStatement = connection.prepareStatement(sql);
            if (null != objects){
                for (int i = 0; i < objects.length; i++) {
                    preparedStatement.setObject(i+1,objects[i]);
                }
            }
            resultSet = preparedStatement.executeQuery();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return resultSet;
    }

    public  static <T> List<T> executeQuery2(Object[] objects,String sql,Class<T> tClass){
        List<T> list = new ArrayList<>();
        try {
            getConnection();
            preparedStatement = connection.prepareStatement(sql);
            if (null != objects){
                for (int i = 0; i < objects.length; i++) {
                    preparedStatement.setObject(i+1,objects[i]);
                }
            }
            resultSet = preparedStatement.executeQuery();
            //创建集合  获取此 ResultSet 对象的列的编号、类型和属性。
            //         返回:此 ResultSet 对象的列的描述
            ResultSetMetaData metaData = resultSet.getMetaData();
            while (resultSet.next()){
                T obj = tClass.newInstance();
                for (int i = 0; i < metaData.getColumnCount(); i++) {
                    // 获取列名  根据下标(从1开始)
                    String colName = metaData.getColumnName(i+1);
                    // 根据列名 获取 值
                    Object value = resultSet.getObject(colName);
                    //利用BeanUtils工具栏,创建对象
                    BeanUtils.setProperty(obj,colName,value);
                }
                //将组装后的结果 保存到list中
                list.add(obj);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } finally {
            closeAll();
        }
        return list;
    }

    public static void closeAll() {
        try {
            if(null != resultSet)
                resultSet.close();
            if(null != preparedStatement)
                preparedStatement.close();
            if(null != connection)
                connection.close();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
}

我们利用数据库中的属性名、值去包装类主要是利用BeanUtils工具类,他也需要导jar包。commons-beanutils-1.9.3 jar

再来一个测试类测一下工具是否好用:

import org.westos.demo.BaseDao;
import org.westos.entity.Student;
import java.util.List;

public class Test {
    public static void main(String[] args) {
        String sql = "select * from student WHERE studentNo = ? AND loginPwd = ? ";
        Object[] objects = {1011,"123456"};
        List<Student> studentList = BaseDao.executeQuery2(objects,sql,Student.class);
        for (Student student : studentList) {
            System.out.println(student.getStudentname());
        }

    }
}

在这里插入图片描述

我们可以看到,有了工具类后,我们只需要输入sql语句以及条件值就可以,他会创建好对象给我们,我们有一个集合去收就可以。再取数据用就可以后用我们java熟悉的get/set方法就ok。

我之前遇到包装对象出错问题,你要先确定你的属性名、数据类型和你的数据库中是一致的,然后还是出错可能因为beanutils1.9.3的包太高级,利用Fasthashmap创建对象,有的Java版本低可能会失败,所以需要找1.8的beanutils包就可以了。

好了,本次分享就到这里,希望对你有帮助,有问题请批评指正,谢谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
package com.hexiang.utils.dao; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.sql.DataSource; import org.apache.log4j.Logger; public class DBConnection { /** * 获得与数据库连接 * * @param path * @return Connection */ public static Connection getConn(String classDriver, String url, String user, String pwd) { try { Class.forName(classDriver); return DriverManager.getConnection(url, user, pwd); } catch (ClassNotFoundException ex) { ex.printStackTrace(); } catch (SQLException ex) { ex.printStackTrace(); } return null; } public static Connection getConn(DataSource dataSource) { try { return dataSource.getConnection(); } catch (SQLException ex) { ex.printStackTrace(); } return null; } public static Connection getConn(String jndiName) { try { Context ctx; ctx = new InitialContext(); DataSource dataSource = (DataSource) ctx.lookup("java:comp/env/" + jndiName); return dataSource.getConnection(); } catch (NamingException ex) { ex.printStackTrace(); } catch (SQLException ex) { ex.printStackTrace(); } return null; } public static Connection getConn(Properties properties) { try { String driver = properties.getProperty("jdbc.driverClassName"); String url = properties.getProperty("jdbc.url"); String user = properties.getProperty("jdbc.username"); String password = properties.getProperty("jdbc.password"); Class.forName(driver); return DriverManager.getConnection(url, user, password); } catch (ClassNotFoundException ex) { ex.printStackTrace(); } catch (SQLException ex) { ex.printStackTrace(); } return null; } /** * oracle连接 * * @param path * @return Connection */ public static Connection getOracleConn(String

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值