2.数据库CRUD操作

1. statement操作数据库(有SQL注入问题)

// 使用Statement的弊端:需要拼写sql语句,并且存在SQL注入的问题
    public void testLogin() {
       Scanner in=new Scanner(System.in);
       System.out.print("请输入账户名:");
       String userName=in.nextLine();
       System.out.print("请输入密码:");
       String password=in.nextLine();
       String sql=
               "SELECT user,password \n" +
               "FROM user_table \n" +
               "WHERE user='"+userName+"' AND password='"+password+"'";
       User returnUser=get(sql,User.class);
       if(returnUser!=null)
           System.out.println("登录成功");
       else  System.out.println("登录失败");
    }

1.1 SQL注入问题

// userName为1’ OR
// password为=‘1’ OR ‘1’ = '1
这时查询语句恒成立

SELECT USER,PASSWORD 
FROM user_table 
WHERE USER = '1' OR ' AND PASSWORD = '='1' OR '1' = '1';

2. preparedStatement(解决SQL注入问题)

PreparedStatement先将sql语句预处理,在向里面填充语句,解决sql注入问题,方面高效image.png
2.1 添加数据操作
try,catch环绕ctrl,alt,t一起按下

//    向customers表中插入一条数据
    public void insertTest()  {
//        1.读取配置信息
        Connection conn=null;
        PreparedStatement ps=null;
        try{
            ResourceBundle rb=ResourceBundle.getBundle("jdbc");
            String url=rb.getString("url");
            String user= rb.getString("user");
            String password=rb.getString("password");
            String driverClass=rb.getString("driverClass");
//        2.加载驱动
            Class.forName(driverClass);
//        3.建立连接
            conn=  DriverManager.getConnection(url,user,password);
        System.out.println(conn);
//        conn.commit();
//        4.预编译sql语句,返回preparedStatement实例
            String sql="insert into customers(name,email,birth)values(?,?,?)";
            ps=conn.prepareStatement(sql);
//        5.填充占位符,下标从1开始
            ps.setString(1,"sad");
            ps.setString(2,"sad@qq.com");
            SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
            String st="2021-10-25";
            java.util.Date d=sdf.parse(st);
            ps.setDate(3,new java.sql.Date(d.getTime()));
        6.执行操作
            ps.execute();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
        7.关闭连接
            if(ps!=null){
                try {
                    ps.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if(conn!=null){
                try {
                    conn.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }
    }

2.2 添加数据操作的封装

工具类

//    获取连接
    public static Connection getConnection() throws Exception {
//        1.资源配置的获取
        ResourceBundle rb=ResourceBundle.getBundle("jdbc");
        String url=rb.getString("url");
        String user= rb.getString("user");
        String password=rb.getString("password");
        String driverClass=rb.getString("driverClass");
//        2.加载驱动
        Class.forName(driverClass);
//        3.建立连接
        Connection conn=  DriverManager.getConnection(url,user,password);
        return conn;
    }
//    连接资源的关闭
    public static void closeResource(Connection conn, PreparedStatement ps){
//        7.关闭连接
        if(ps!=null){
            try {
                ps.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }

封装后的实现代码

public void insertTest2()  {
        Connection conn=null;
        PreparedStatement ps=null;
        try{
//            1.获取数据库连接
            conn=JDBCUtils.getConnection();
//            2.预编译sql语句,返回对象的实例
            String sql="insert into customers(name,email,birth)values(?,?,?)";
            ps=conn.prepareStatement(sql);
//            3.填充占位符,下标从1开始
            ps.setString(1,"ccc");
            ps.setString(2,"ccc@qq.com");
            SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
            String st="2021-10-25";
            java.util.Date d=sdf.parse(st);
            ps.setDate(3,new java.sql.Date(d.getTime()));
        4.执行操作
            ps.execute();
        }catch(Exception e){
            e.printStackTrace();
        }finally {
//            5,资源的关闭
            JDBCUtils.closeResource(conn,ps);
        }
    }

2.3 通用的数据库增删改操作

如果表名或者其他字段和关键字重复,需要使用``来包裹起来该字段防止报错
例如:order是关键字,需要 order
通用增删改模板

//    增删改操作通用模板
    public void updateTable(String sql,Object...vals){
//        可变形参vals的数量就是占位符的数量
            Connection conn=null;
            PreparedStatement ps=null;
        try {
//        1.获取连接
            conn=JDBCUtils.getConnection();
//        2,实例化PreparedStatement对象
            ps=conn.prepareStatement(sql);
//        3.填充占位符
            for(int i=0;i<vals.length;i++){
                ps.setObject(i+1,vals[i]);
            }
//        4.执行
            ps.execute();//返回的是boolean类型,增删改返回false,查询返回true
            //ps.exeUpdate();//返回的是更新的数目 int类型
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //        5.关闭资源
            JDBCUtils.closeResource(conn,ps);
        }
    }

执行语句

		test t=new test();
//        增加
        String sql0="insert into customers(name,email,birth) values(?,?,?)";
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
        String str="2000-01-01";
        Date d=null;
        try {
            d=sdf.parse(str);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        t.updateTable(sql0,"ddd","ddd@qq.com",new java.sql.Date(d.getTime()));
//        删除
        String sql1="delete from customers where name=?";
        t.updateTable(sql1,"sad");
//        更改
        String sql="update customers set name=? where id=?";
        t.updateTable(sql,"莫扎特",18);

2.4数据库查询操作

起别名之后的where筛选条件还是只能使用原有表的字段
image.png

2.4.1 针对Customers表的查询操作

//    查询Customers表的数据
    public void testQuery1(){
        Connection conn=null;
        PreparedStatement ps=null;
        ResultSet resultSet=null;
        try {
//        1.获取连接
            conn = JDBCUtils.getConnection();
//        2.预编译sql语句
            String sql = "select id,`name`,email,birth from customers where id=?";
            ps = conn.prepareStatement(sql);
//        3.填充占位符
            ps.setInt(1, 36);
//        4.执行并返回结果集
            resultSet = ps.executeQuery();
//        结果集的next()方法刚开始指针是指向,第一个元素前面的元素
//        返回boolean类型,有下一条数据,返回true指针下移
            if (resultSet.next()) {
//            获取当前数据的所有字段值
                int id = resultSet.getInt(1);
                String name = resultSet.getString(2);
                String email = resultSet.getString(3);
                Date birth = resultSet.getDate(4);
//            将数据封装成一个对象
                Customers c = new Customers(id, name, email, birth);
                System.out.println(c);
            }
        }catch(Exception e){
            e.printStackTrace();
        }finally {
//            5.关闭资源
            JDBCUtils.closeResource(conn,ps,resultSet);
        }
    }

2.4.2 Customers对象

部分代码

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

image.png

2.4.3 针对Customers表的通用查询操作

//    Customers表的通用查询操作
    public Customers testQuery2(String sql,Object...vals){
        Connection conn= null;
        PreparedStatement ps= null;
        ResultSet rs= null;
        try {
//        1.获取连接
            conn = JDBCUtils.getConnection();
//        2.预编译sql语句
            ps = conn.prepareStatement(sql);
//        3.填充占位符
            for(int i=0;i<vals.length;i++){
                ps.setObject(i+1,vals[i]);
            }
//        4.执行并返回结果集
            rs = ps.executeQuery();
//        5.获取结果集的元数据
            ResultSetMetaData rsmd=rs.getMetaData();
            int columnCount=rsmd.getColumnCount();//知道返回结果有多少列
//        6.返回结果
            if(rs.next()){
                Customers cus=new Customers();
                for(int i=0;i<columnCount;i++){
                    Object columnVal=rs.getObject(i+1);//返回这一列的值
                    String columnName=rsmd.getColumnName(i+1);//返回这一列的列名
    //                反射为对象赋值
                    Field field=cus.getClass().getDeclaredField(columnName);//根据列名获取字段
//                    需要DeclareField获取所有字段
                    field.setAccessible(true);//打破封装,外部也可以修改这个属性
                    field.set(cus,columnVal);
                }
                return cus;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //        7.关闭连接
            JDBCUtils.closeResource(conn,ps,rs);
        }
        return null;//这里仅当try没有返回时才去执行
    }
//    如果try,finally中都有return,忽略try中的return
//    try中的return保存在一个临时变量中,finally执行完毕后返回这个临时变量

执行语句和返回结果

		test1 t=new test1();
        String sql="select id,`name`,email,birth from customers where id=?";
        System.out.println(t.testQuery2(sql,36));
        String sql1="select id,`name`,email from customers where `name`=?";
        System.out.println(t.testQuery2(sql1,"周杰伦"));

//返回结果
        Customers{id=36, name='ddd', email='ddd@qq.com', birth=2000-01-01}
        Customers{id=10, name='周杰伦', email='zhoujl@sina.com', birth=null}

2.4.4 针对Order表的通用查询操作

//    可以解决表中字段名和类中属性名不一致的情况
    public Order testQuery1(String sql,Object...vals)  {
        Connection conn= null;
        PreparedStatement ps= null;
        ResultSet rs= null;
        try {
//        1.获取连接
            conn = JDBCUtils.getConnection();
//        2.预编译sql语句,占位符赋值
            ps = conn.prepareStatement(sql);
            for(int i=0;i<vals.length;i++){
                ps.setObject(i+1,vals[i]);
            }
//        3.获取结果集
            rs = ps.executeQuery();//结果集存放的是数据
            ResultSetMetaData rsmd=rs.getMetaData();//元数据存放的是修饰数据的内容
            int columnCount=rsmd.getColumnCount();
//        4.生成结果集对象
            if(rs.next()){
                Order order=new Order();
                for(int i=0;i<columnCount;i++){
                    Object columnVal=rs.getObject(i+1);
//                    这里是获取mysql表的实际名称
//                    String columnName=rsmd.getColumnName(i+1);//这里的结果名是mysql表中的名称
//                    获取mysql表的别名,如果没有别名,默认真实名称
                    String columnLable=rsmd.getColumnLabel(i+1);//这里结果是mysql表中的别名
//                    需要Mysql表中的名称和类中的属性名一致,才能反射成功,需要使用别名
                    Field field=order.getClass().getDeclaredField(columnLable);
                    field.setAccessible(true);
                    field.set(order,columnVal);
                }
                return order;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
//        5.关闭资源连接
            JDBCUtils.closeResource(conn,ps,rs);
        }
        return null;
    }

order对象

public class Order {
    private int id;
    private String name;
    private Date date;

执行语句和返回结果

		test2 t=new test2();
//        这里sql语句字段的别名要和类中属性名一致,使得反射成功
        String sql="select order_id `id`,order_name `name`,order_date `date` from `order` where order_id=?";
        System.out.println(t.testQuery1(sql,1));

//返回结果
	Order{id=1, name='AA', date=2010-03-04}

2.4.5 查询操作流程

image.png

2.4.6 针对不同表的通用查询(返回一条记录)

//    <T>表示这是一个泛型方法,返回类型为T,T类型由实参传入
    public <T> T query1(Class<T> clazz,String sql,Object...vals){
        Connection conn= null;
        PreparedStatement ps= null;
        ResultSet rs= null;
        try {
//            1.获取数据库连接
            conn = JDBCUtils.getConnection();
//            2.预编译sql语句,占位符赋值
            ps = conn.prepareStatement(sql);
            for(int i=0;i<vals.length;i++){
                ps.setObject(i+1,vals[i]);
            }
//            3.获取结果集
            rs = ps.executeQuery();
            ResultSetMetaData rsmd=rs.getMetaData();
            int columnCount=rsmd.getColumnCount();
//            4,生成返回的结果集对象
            if(rs.next()){
//                通过声明的构造器,new一个T类型的对象
                T t=clazz.getDeclaredConstructor().newInstance();
                for(int i=0;i<columnCount;i++){
                    Object columnVal=rs.getObject(i+1);
                    String columnLabel=rsmd.getColumnLabel(i+1);
//                    反射为对象属性赋值
                    Field field=t.getClass().getDeclaredField(columnLabel);
                    field.setAccessible(true);
                    field.set(t,columnVal);
                }
                return t;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
//            5.关闭资源连接
            JDBCUtils.closeResource(conn,ps,rs);
        }
        return null;
    }

执行语句和返回结果

		test3 tes=new test3();
        String sql1="select order_id `id`,order_name `name`,order_date `date` from `order` where order_id=?";
        System.out.println(tes.query1(Order.class,sql1,1));
        String sql2="select id,`name`,email,birth from customers where id=?";
        System.out.println(tes.query1(Customers.class,sql2,36));

//返回结果
Order{id=1, name='AA', date=2010-03-04}
Customers{id=36, name='ddd', email='ddd@qq.com', birth=2000-01-01}

2.4.7 针对不同表的通用查询(返回多条记录)

    public <T> List<T> query2(Class<T> clazz, String sql, Object...vals){
        Connection conn= null;
        PreparedStatement ps= null;
        ResultSet rs= null;
        try {
//            1.获取数据库连接
            conn = JDBCUtils.getConnection();
//            2.预编译sql语句,占位符赋值
            ps = conn.prepareStatement(sql);
            for(int i=0;i<vals.length;i++){
                ps.setObject(i+1,vals[i]);
            }
//            3.获取结果集
            rs = ps.executeQuery();
            ResultSetMetaData rsmd=rs.getMetaData();
            int columnCount=rsmd.getColumnCount();
//            4,生成返回的结果集对象
            List<T> lists=new ArrayList<>();
            while(rs.next()){//这里循环一次构造一个对象,即表的一行
//                通过声明的构造器,new一个T类型的对象
                T t=clazz.getDeclaredConstructor().newInstance();
                for(int i=0;i<columnCount;i++){
                    Object columnVal=rs.getObject(i+1);
                    String columnLabel=rsmd.getColumnLabel(i+1);
//                    反射为对象属性赋值
                    Field field=t.getClass().getDeclaredField(columnLabel);
                    field.setAccessible(true);
                    field.set(t,columnVal);
                }
                lists.add(t);
            }
            return lists;
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
//            5.关闭资源连接
            JDBCUtils.closeResource(conn,ps,rs);
        }
        return null;
    }

执行语句

		String sql3="select order_id `id`,order_name `name`,order_date `date` from `order`";
        List lists3=tes.query2(Order.class,sql3);
        lists3.forEach(o->System.out.println(o));
        String sql4="select id,`name`,email,birth from customers";
        List lists4=tes.query2(Customers.class,sql4);
        lists4.forEach(o->System.out.println(o));

2.4.8 小结

image.png

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值