JDBC 程序编写

 

1.大致流程

 

 

2.创建数据库连接的五种方式

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;

import org.junit.Test;

public class ConnectionTest {
    //方式一
    @Test
    public void testConnection1() throws SQLException {
        
        
        //获取Driver的实现类对象
        Driver driver = new com.mysql.jdbc.Driver();
        
        //获取连接参数
        String url = "jdbc:mysql://localhost:3306/test";
        Properties info = new Properties();
        info.setProperty("user","root");
        info.setProperty("password", "root@123");
        //获取连接实例
        Connection conn = driver.connect(url, info);
        System.out.println(conn);
            
    }
    //方式二,对方式一的迭代:在如下的程序中不出现第三方的API,使得程序具有更好的可移植性
    @Test
    public void testConnection2() throws Exception{
        //1.获取Driver的实现类对象
        Class clazz = Class.forName("com.mysql.jdbc.Driver");
        Driver driver = (Driver) clazz.newInstance();
        //2.提供要连接的数据库
        String url = "jdbc:mysql://localhost:3306/test";
        //3.提供连接需要的用户名和密码
        Properties info = new Properties();
        info.setProperty("user","root");
        info.setProperty("password", "root@123");
        //4.获取链接
        Connection conn = driver.connect(url, info);
        System.out.println(conn);
        
    }
    //方式三,使用DriverManager替换Driver
    @Test
    public void testConnection3() throws Exception {
        
        //1.获取Driver实现类的对象
        Class clazz = Class.forName("com.mysql.jdbc.Driver");
        Driver driver = (Driver) clazz.newInstance();
        
        //2.提供另外三个连接的基本信息
        String url = "jdbc:mysql://localhost:3306/test";
        String user = "root";
        String password = "root@123";
        //3.获取链接
        
        //注册驱动
        DriverManager.registerDriver(driver);
        //获取链接
        Connection conn = DriverManager.getConnection(url, user, password);
        System.out.println(conn);
    }
    
    //方式四,可以只是加载驱动,不用显式地注册驱动了
    @Test
    public void testConnection4() throws Exception {
        //1.提供三个连接的基本信息
        String url = "jdbc:mysql://localhost:3306/test";
        String user = "root";
        String password = "root@123";
        
        //2.加载Driver
        Class.forName("com.mysql.jdbc.Driver");
        //相较于方式三可以省略如下的操作
//        Driver driver = (Driver) clazz.newInstance();
//        //注册驱动
//        DriverManager.registerDriver(driver);
        //为什么可以省略上述操作呢
        /*
         * 在mysql的Driver实现类中,声明了注册驱动的静态代码块
         * 
         */
        //3.获取链接
        Connection conn = DriverManager.getConnection(url, user, password);
        System.out.println(conn);
    }
    
    //方式五(final版):将数据库连接需要的4个基本信息声明在配置文件中,通过读取配置文件的方式,获取连接
    /*
     * 此种方式的好处?
     * 1.实现了数据与代码的分离,实现了解耦
     * 2.如果需要修改配置文件信息,可以避免程序重新打包
     */
    @Test
    public void testConnection5() throws Exception {
        //1.读取配置文件中的四个基本信息
        InputStream is = ConnectionTest.class.getClassLoader().getResourceAsStream("jdbc.properties");
        Properties props = new Properties();
        props.load(is);
        String user = props.getProperty("user");
        String password = props.getProperty("password");
        String url = props.getProperty("url");
        String driver = props.getProperty("driver");
        //2.加载驱动
        Class.forName(driver);
        //3.获取连接
        Connection conn = DriverManager.getConnection(url, user, password);
        System.out.println(conn);
    }
    

}

通用方法:获取链接以及关闭资源单独创建工具类

/*
 * 操作数据库的工具类
 */

public class JDBCUtils {
    
    //获取数据库的连接
    public static Connection getConnection() throws Exception {
        //1.读取配置文件中的四个基本信息
        InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
        Properties props = new Properties();
        props.load(is);
        String user = props.getProperty("user");
        String password = props.getProperty("password");
        String url = props.getProperty("url");
        String driver = props.getProperty("driver");
        //2.加载驱动
        Class.forName(driver);
        //3.获取连接 
        Connection conn = DriverManager.getConnection(url, user, password);
        return conn;
    }
    
    //关闭资源的操作
    public static void closeResource(Connection conn,PreparedStatement ps) {
        if(conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(ps != null) {
            try {
                ps.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    
}

通用的增删改操作

    @Test
    public void testCommonUpdate() {
//        String sql = "delete from customers where id = ?";
//        update(sql, 3);
        
        String sql = "update `order` set order_name = ? where order_id = ?";
        update(sql, "DD","2");
    }
    
    //通用的增删改操作
    public void update(String sql,Object ...args){//sql中占位符的个数应该与可变形参长度一致
        Connection conn = null;
        PreparedStatement ps = null;
        try {
            //1.获取数据库连接
            conn = JDBCUtils.getConnection();
            //2.预编译sql语句,返回PreparedStatement实例
            ps = conn.prepareStatement(sql);
            //3.填充占位符
            for(int i = 0;i < args.length;i++) {
                ps.setObject(i+1, args[i]);
            }
            //4.执行
            ps.execute();
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            //5.关闭资源
            JDBCUtils.closeResource(conn, ps);
        }
    }

 

 * ORM编程思想(object relating mapping)

  一个数据表对应一个Java类

  表中的一条记录对应Java类的一个对象

 表中的一个字段对应Java类的一个属性

 

/*
 * 针对order表的通用查询操作
 */
public class OrderForQuery {
    
    /*
     * 针对表的字段名与类的属性名不相同的情况,
     * 1.必须声明sql时,使用类的属性名来命名字段的别名
     * 2.使用ResultSetMetaData时,需要使用getColumnLabel()来替换getColumnName(),
     *      获取列的名。
     * 说明:如果sql中没有给字段取别名,getColumnLabel()获取的就是列名
     */
    
    @Test
    public void testOrderQuery() {
        String sql = "select order_id,order_name,order_date from `order` where order_id = ? ";
        Order order = testOrderQuery(sql, 2);
        System.out.println(order);
    }
    
    public Order testOrderQuery(String sql,Object ...args){
        Connection conn = null;
        PreparedStatement ps = null;    
        ResultSet rs = null;
                
        try {
            //建立数据库连接
            conn = JDBCUtils.getConnection();
            //预编辑sql语句,返回prepareStatement实例
            ps = conn.prepareStatement(sql);
            //填充占位符
            for (int i = 0; i < args.length; i++) {
                ps.setObject(i + 1, args[i]);
            }
            //执行
            ps.executeQuery();
            //获取结果集
            rs = ps.getResultSet();
            //获取结果集的元数据
            ResultSetMetaData rsmd = rs.getMetaData();
            int columnCount = rsmd.getColumnCount();
            if(rs.next()) {
                Order order = new Order();
                //循环每一行
                for (int i = 0; i < columnCount; i++) {
                    //获取每一列的数据值
                    Object columnValue = rs.getObject(i + 1);
                    //getColumnName 不推荐使用,建议使用getColumnLabel获取列名
                    String columnName = rsmd.getColumnName(i + 1);
                    Field field = Order.class.getDeclaredField(columnName);
                    field.setAccessible(true);
                    field.set(order, columnValue);
                }
                return order;
        }
        
    }catch (Exception e) {
        e.printStackTrace();
    }finally{
        JDBCUtils.closeResource(conn, ps, rs);
    }
    
    return null;
    
    }
}

通用查询的流程:

 

 

 

通用查询终极版:

public class CommonQuery {
    
    @Test
    public void testGetForList() {
        String sql = "SELECT id,name,email,birth FROM customers WHERE id < ?";
        List<Customer> list = getForList(Customer.class, sql, 12);
        list.forEach(System.out::println);
        
        String sql1 = "SELECT order_id,order_name,order_date FROM `order` WHERE order_id< ?";
        List<Order> list1 = getForList(Order.class, sql1, 4);
        list1.forEach(System.out::println);
        
    }
    
    @Test
    public void testGetInstance() {
        
        String sql = "SELECT id,name,email,birth FROM customers WHERE id = ? ";
        Customer cust = getInstance(Customer.class, sql, 2);
        System.out.println(cust);
        
    }
    
    public <T> List<T> getForList(Class<T> clazz, String sql, Object ...args){
        Connection conn =  null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        
        try {
            //建立连接
            conn = JDBCUtils.getConnection();
            //预编辑sql语句,返回preparedStatement对象实例
            ps = conn.prepareStatement(sql);
            //填充占位符
            for (int i = 0; i < args.length; i++) {
                ps.setObject(i + 1 , args[i]);
            }
            //执行语句
            rs = ps.executeQuery();
            //获取元数据集
            ResultSetMetaData rsmd = rs.getMetaData();
            //通过元数据集获取列数
            int columnCount = rsmd.getColumnCount();
            //创建集合对象
            ArrayList<T> list = new ArrayList<T>();
            //判断是否有下一行并换行
            while(rs.next()) {
                T t = clazz.newInstance();
                for (int i = 0; i < columnCount; i++) {
                    //通过结果集获取列值
                    Object columnValue = rs.getObject(i + 1);
                    //通过元数据集获取列名
                    String columnLabel = rsmd.getColumnLabel(i + 1);
                    //通过反射获取columnName属性,并为属性赋值为columnValue
                    Field field  = clazz.getDeclaredField(columnLabel);
                    field.setAccessible(true);
                    field.set(t, columnValue);
                    
                }
                list.add(t);
            }
            return list;
        }catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    
    public <T> T getInstance(Class<T> clazz, String sql, Object ...args){
        
        Connection conn =  null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            //建立连接
            conn = JDBCUtils.getConnection();
            //预编辑sql语句,返回preparedStatement对象实例
            ps = conn.prepareStatement(sql);
            //填充占位符
            for (int i = 0; i < args.length; i++) {
                ps.setObject(i + 1 , args[i]);
            }
            //执行语句
            rs = ps.executeQuery();
            //获取元数据集
            ResultSetMetaData rsmd = rs.getMetaData();
            //通过元数据集获取列数
            int columnCount = rsmd.getColumnCount();
            //判断是否有下一行并换行
            while(rs.next()) {
                T t = clazz.newInstance();
                for (int i = 0; i < columnCount; i++) {
                    //通过结果集获取列值
                    Object columnValue = rs.getObject(i + 1);
                    //通过元数据集获取列名
                    String columnLabel = rsmd.getColumnLabel(i + 1);
                    //通过反射获取columnName属性,并为属性赋值为columnValue
                    Field field  = clazz.getDeclaredField(columnLabel);
                    field.setAccessible(true);
                    field.set(t, columnValue);
                    
                }
                return t;
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

 

 

Statement 和PrepareStatement

 * 除了解决Statement的拼串导致的sql注入问题之外,PreparedStatement还有如下好处:

 * 1.PreparedStatement操作Blob的数据,而Statement做不到。

 * 2.PreparedStatement 可以实现更高效的批量操作。

 

批量插入:

1.

ps.addBatch();

ps.excuteBatch()

ps.clearbatch()

2.

setAutoCommit(false);

conn.commit();

posted @ 2021-10-31 21:31  donkey8  阅读(89)  评论(0)    收藏  举报