使用PreparedStatement完成增删改查

使用PreparedStatement完成增删改查

ClassLoader.getSystemClassLoader()

使用系统的构造器

package com.nenu.ps.crud;

import com.nenu.connection.ConnectionTest;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;

public class PreparedStatementUpdateTest {
    //向数据表中添加数据
    @Test
    public void testInsert() throws Exception {
        Connection conn = null;
        PreparedStatement ps = null;
        try {
            InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
            Properties pros = new Properties();
            pros.load(is);
            String user = pros.getProperty("user");
            String password = pros.getProperty("password");
            String url = pros.getProperty("url");
            String driverClass = pros.getProperty("driverClass");
//        2.加载驱动
            Class.forName(driverClass);
            //3.获取连接
            conn = DriverManager.getConnection(url, user, password);
            System.out.println(conn);
            //4.预编译
            String sql = "insert into customers(name,email,birth)values(?,?,?)";
//        5.?占位符
            ps = conn.prepareStatement(sql);
            ps.setString(1, "哪吒");
            ps.setString(2, "nezha@gmail.com");
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            java.util.Date date = sdf.parse("1000-01-01");
            Timestamp t = new Timestamp(date.getTime());
            ps.setTimestamp(3, t);
            //6.执行sql
            ps.execute();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        } finally {
            //7.资源的关闭
            try {
                ps.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            try {
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}

使用了ps能有效避免sql注入
但是代码耦合度还有点大
所以我们要封装

package com.nenu.util;

import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

public class JDBCutil {
    public static Connection getConnection() throws Exception {
        InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
        Properties pros = new Properties();
        pros.load(is);
        String user = pros.getProperty("user");
        String password = pros.getProperty("password");
        String url = pros.getProperty("url");
        String driverClass = pros.getProperty("driverClass");
//        2.加载驱动
        Class.forName(driverClass);
        //3.获取连接
        Connection conn = DriverManager.getConnection(url, user, password);
        System.out.println(conn);
        return conn;
    }

    public static void closeResourese(Connection conn, PreparedStatement ps) {
        try {
            if (ps!=null) {
                ps.close();
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        try {
            if (conn!=null) {
                conn.close();
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
    public static void closeResourese(Connection conn, PreparedStatement ps , ResultSet resultSet) throws SQLException {
        try {
            if (resultSet!=null) {
                resultSet.close();
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        try {
            if (ps!=null) {
                ps.close();
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        try {
            if (conn!=null) {
                conn.close();
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }

    }
}

我们将ps获取连接及关闭专门写到一个类中,因为我只要想使用JDBC都会用到这个类

package com.nenu.bean;

import java.sql.Date;

//ORM变成思想
/*
  一个数据对应一个java类
  表中的一条记录对应java类的一个对象
  表中的一个字段对应java类的属性

 */
public class Customer {
    private int id;
    private String name;
    private String email;
    private Date birth;

    public Customer(int id, String name, String email, Date birth) {
        this.id = id;
        this.name = name;
        this.email = email;
        this.birth = birth;
    }

    @Override
    public String toString() {
        return "Customer{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", email='" + email + '\'' +
                ", birth=" + birth +
                '}';
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Date getBirth() {
        return birth;
    }

    public void setBirth(Date birth) {
        this.birth = birth;
    }
}

再把我们想更改数据的的一些信息封装起来
我们写更新的时候就只用在这里面直接调用我们封装好的

@Test
    public void testUpdate() throws Exception {
//        获取数据库连接
        Connection conn = null;
        PreparedStatement ps = null;
        try {
            conn = JDBCutil.getConnection();
//        预编译sql语句,返回PreparedStatement的实例
            String sql="update customers set name =? where id=?";
            ps = conn.prepareStatement(sql);
//        填充占位符
            ps.setObject(1,"莫扎特");
            ps.setObject(2,18);
//        执行
            ps.execute();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
//        资源的关闭
            try {
                JDBCutil.closeResourese(conn, ps);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

但是这种方法我们还是无法做到增删改通用一个代码

 @Test
    public static void update(String sql, Object... args) throws Exception {//sql当中占位符的个数应该与可变形参长度相同
        Connection conn = null;
        PreparedStatement ps = null;
        try {
            conn = JDBCutil.getConnection();
            ps = conn.prepareStatement(sql);
            for (int i = 0; i <args.length ; i++) {
              ps.setObject(i+1,args[i]);
            }
            ps.execute();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {

        JDBCutil.closeResourese(conn,ps);

        }
    }

    public static void main(String[] args) throws Exception {
        String sql = "delete from customers where id =?";
        update(sql,3);
    }

因为我们不知道查询的东西是什么属性所以统一使用setObject,…args里面会与占位符长度相同,这样就能在里面填充。不过调用update方法的时候不能在idea使用Test,直接使用main方法就好。
我们实现了增删改,还没有实现查询,我们为什么要查询单独列出来呢 因为增删改都只是去改数据库里面的数据,而查询我们是需要一个结果集的

ORM编程思想

在这里我们引入一个编程思想
/*
一个数据对应一个java类
表中的一条记录对应java类的一个对象
表中的一个字段对应java类的属性

*/

package com.nenu.ps.crud;

import com.nenu.bean.Customer;
import com.nenu.util.JDBCutil;
import org.junit.Test;

import java.sql.*;

public class CustomerForQuery {
    @Test
    public void testQuery1() throws Exception {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet resultSet = null;
        try {
            conn = JDBCutil.getConnection();
            String sql = "select id,name,email,birth from customers where id=?";
            ps = conn.prepareStatement(sql);
            ps.setObject(1,1);
//        执行,并返回结果集
            resultSet = ps.executeQuery();
//        处理结果集
            if(resultSet.next()){
                //判断结果集下一条是否有数据,像hashnext与next一半的功能
                int id=resultSet.getInt(1);
                String name=resultSet.getString(2);
                String email =resultSet.getString(3);
                Date birth = resultSet.getDate(4);
    //            Object[] data =new Object[]{id,name,email,birth};
                Customer customer = new Customer(id,name,email,birth);
                System.out.println(customer);

            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {

            try {
                JDBCutil.closeResourese(conn,ps,resultSet);
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}

我们用ResultSet类将结果集拿出来,在customer中进行了无参构造,有参构造还有封装还重写了toString方法。
然后老规矩将代码 与查询的东西分开

import com.nenu.bean.Order;
import com.nenu.util.JDBCutil;
import org.junit.Test;

import java.lang.reflect.Field;
import java.sql.*;

public class OrderQuery {
    @Test
//    通用
    public static Order orderForQuery(String sql, Object... args)  {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            conn = JDBCutil.getConnection();
            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();
            if(rs.next()){
                Order order =new Order();
                for (int i = 0; i <columnCount ; i++) {
    //获取每个列的列值:通过ResultSet
                    Object columnValue = rs.getObject(i+1);
    //                获取每个列的列名,通过ResultSetMetaData
//                    获取列的别名:getColumnLabel
//                    String columnName = rsmd.getColumnName(i + 1);
                    String columnLabel = rsmd.getColumnLabel(i + 1);
                    //                通过反射,将对象指定名columnName的属性赋值为指定的值columnValue
                    Field field = Order.class.getDeclaredField(columnLabel);
                    field.setAccessible(true);
                    field.set(order,columnValue);
                }
             return order;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {

            try {
                JDBCutil.closeResourese(conn,ps,rs);
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            return null;
    }
    }

    public static void main(String[] args) {

        String sql="select order_id orderId,order_name orderName,order_date orderDate from `order` where order_id=?";
        Order order = orderForQuery(sql, 2);
        System.out.println(order);
    }

因为我们这次用的是order表,但是里面的列名却和我们封装类里面的的属性不一样,这时候就查找不到该数据库里面的列名,所以我们用了别名查找。

Java类型SQL类型
booleanBIT
byteTINYINT
shortSMALLINT
intINTEGER
longBIGINT
StringCHAR,VARCHAR,LONGVARCHAR
byte arrayBINARY , VAR BINARY
java.sql.DateDATE
java.sql.TimeTIME
java.sql.TimestampTIMESTAMP
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值