JDBC(一)

一、什么是JDBC

JDBC顾名思义是Java连接数据库,是一套规范(接口)那数据库厂商需要实现这套接口
        //才能跟数据库建立连接,我们把数据库厂商写的这套实现类,称之为数据库驱动

二、API中与JDBC相关的接口和类(以及对应的方法)

CallableStatement 用于执行 SQL存储过程的接口

Result

三、JDBC连接数据库(初涉)

需求1:向数据库中插入一行数据

package org.westos.demo;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
public class JDBCTest {
    public static void main(String[] args) throws Exception {
        //1.导入MySQL数据库驱动jar包
        //2.注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        //3.获取连接对象,根据数据库建立连接
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "123456");
        //4.获取操作对象
        Statement statement = conn.createStatement();
        //定义sql语句
        String sql = "insert into users values('zhaoliu','654321')";
        //5.执行操作
        statement.executeUpdate(sql);
        //释放资源
        conn.close();
        statement.close();
    }
}

说明:上面的太麻烦,每次都要进行修改;因此写成工具类并写成对应的配置文件(后续用c3p0进行连接)

工具类

package org.wzj.com;
import java.io.FileReader;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
 * 说明:自己写的连接工具类
 * 原因:要了解底层,为以后底层开发打好基础
 */
public class JDBCUtils {
    private static String password;
    private static String username;
    private static String url;
    //构造方法私有化
    private JDBCUtils() {

    }
    static {
        //回顾属性集合类的作用和方法
        Properties properties = new Properties();
        try {
            //配置文件的方式进行读取,建立连接
            properties.load(new FileReader("jdbc.properties"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            Class.forName(properties.getProperty("driverclass"));//注册(反射)
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        //建立连接三要素:(主协议、子协议、IP、端口、数据库)、用户名、密码
        url = properties.getProperty("url");
        username = properties.getProperty("username");
        password = properties.getProperty("password");
    }
    /**
     *
     * @return 连接数据库的对象
     * @throws SQLException
     */
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url,username,password);
    }
    /**
     * 功能:释放资源
     * @param con
     * @param statement
     * @throws SQLException
     */
    public static void close(Connection con, Statement statement) throws SQLException {
        if(con!=null){
            con.close();
        }
        if(statement!=null){
            statement.close();
        }
    }
}

配置文件

driverclass=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test #如果是本地连接可以省略主机(ip)和端口号写成"///"
username=root
password=123456

Statement很容易出现sql注入(危险),因此采取预编译PreparedStatement

需求2:JDBC查询student用户表中的信息

package org.wzj.com;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class JDBCTest {
    public static void main(String[] args) throws SQLException {
        Connection connection = JDBCUtils.getConnection();
        //sql语句(重点掌握!!!)
        String sql ="select *from student ";
        //预编译(防止sql注入)
        PreparedStatement ps = connection.prepareStatement(sql);
        //注意:接受查询的数据是一个容器
        ResultSet resultSet = ps.executeQuery();
        while(resultSet.next()){
            //常用根据列索引找值(从1开始)
            String s1 = resultSet.getString(1);
            String s2 = resultSet.getString(2);
            System.out.println(s1+","+s2);
        }
        JDBCUtils.close(connection,ps);
    }
}

四、批处理

package org.wzj.com;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
/**
 * 说明:批处理
 */
public class JDBCTest02 {
    public static void main(String[] args) throws SQLException {
        Connection connection = JDBCUtils.getConnection();
        String sql="insert into user values(?,?)";//理解占位符的作用
        PreparedStatement statement = connection.prepareStatement(sql);
        //创建一个集合(里面存储数据,然后批量增加)
        ArrayList<User> users = new ArrayList<User>();
        User user=null;
        for(int i=1;i<=100;i++){
            user= new User();//临时用户
            user.setUsername("用户"+i);
            user.setPassword("密码"+i);
            users.add(user);
        }
        // 需求:批处理添加数据
        //遍历集合插入数据
        for(User u:users){
            //对每个占位符进行赋值
            statement.setString(1,u.getUsername());
            statement.setString(2,u.getPassword());
            // 笨办法--statement.executeUpdate();循环一条一条的插入,可以,但是效率不高
            statement.addBatch();//添加到缓存中因为已经预处理过了,不需要写入sql语句了
        }
        statement.executeBatch();//批处理(建立一个缓存,以免每次操作都需要连接)
        //清空批处理
        statement.clearBatch();
        //释放资源
        JDBCUtils.close(connection,statement);
    }
}

说明:

五、JDBC调用存储过程

 存

package org.wzj.com;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Types;
//说明:用Java代码调用存储过程

//需求:调用存储过程,查询数据的条数
public class JDBCTest03 {
    public static void main(String[] args) throws SQLException {
        //(1)倒包后建立数据库的连接对象
        Connection connection = JDBCUtils.getConnection();
        //(2)存储过程本身也是个sql语句
        String sql="call mycall(?)";//存储过程的调用
        //(3)获取操作对象(CallableStatement 专用于执行SQL存储过程的接口)
        CallableStatement call = connection.prepareCall(sql);
        //(4)接受输出参数前,必须声明对应的占位符(这里没有输入,因此不赋值了)
        //说明:参数1:占位符的索引,参数2 参数类型
        call.registerOutParameter(1,Types.INTEGER);
        //(5)调用存储过程(sql语句)
        call.execute();
        //(6)获取结果(对应的位置获取对应类型的值)
        int result = call.getInt(1);
        System.out.println(result);
    }
}

说明:mysql的存储过程可以带输入(in)和输出参数(out)或(inout),但是对于Java来说似乎没有inout的用法

注意1:包含结果参数的形式(带出参数--out)和一个不包含结果参数的形式

注意2:如果 使用结果参数,则必须将其 声明注册out参数;不使用的话就不用声明了

六、JDBC调用函数

需求:根据用户名查出对应的密码

package org.wzj.com;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Types;

//需求:根据传入的用户名返回对应的密码
public class JDBCTest04 {
    public static void main(String[] args) throws SQLException {
        //JDBC调用函数
        //(1)倒包后建立数据库的连接对象
        Connection connection = JDBCUtils.getConnection();
        //(2)存储过程本身也是个sql语句
        String sql="{?=call myfunction(?)}";//存储过程的调用
        //(3)获取操作对象(CallableStatement 专用于执行SQL存储过程的接口)
        CallableStatement call = connection.prepareCall(sql);
        //(4)声明返回值
        call.registerOutParameter(1,Types.VARCHAR);
        //(5)给占位符赋值
        call.setString(2,"用户1");
        //(6)执行
        call.execute();
        //(7)获取结果
        String result = call.getString(1);
        System.out.println(result);
    }
}

说明:

七、JDBC中多表的自增长键问题

    需求:获取最后插入值的自增长键的值

package org.wzj.com;

import java.sql.*;

public class JDBCTest05 {
    public static void main(String[] args) throws SQLException {
        //需求:获取自增长键的值(自增长的插入的最后一个)--一般用在多表中
        Connection connection = JDBCUtils.getConnection();
        //(1)预定义SQL语句
        String sql="insert into user values(?,?)";
        //(2)预编译SQL语句
        PreparedStatement ps = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);//注意
        //(3)插入NULL值--如同mysql中的插入null值,但是Java中不能直接以null的形式直接插入
        ps.setNull(1, Types.NULL);//插入NULL值
        ps.setString(2,"李四");
        ps.executeUpdate();
        //(4)向订单表中插入数据(下订单)
        String insert="insert into orders values(?,?,?)";
        PreparedStatement pres = connection.prepareStatement(insert);//
        pres.setInt(1,1);
        pres.setInt(2,1500);
        //(5)获取用户表执行后的"当前"自增长键
        ResultSet autokeys = ps.getGeneratedKeys();//获取当前自增长键
        int var =0;
        while(autokeys.next()){
            var=autokeys.getInt(1);(此位置是1--批处理是不是获取多个)
            System.out.println("获取到更新的主键值了");
        }
        pres.setInt(3,var);
        pres.executeUpdate();
        JDBCUtils.close(connection,pres);
    }
}

说明:

八、细节


猜你喜欢

转载自blog.csdn.net/wzj_110/article/details/80569592