Java JDBC的基础知识(四)

之前学习了如何创建一个数据库工具类,如下:

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

public class DBUtil {
    // 私有化构造方法
    private DBUtil() {
    }

    private static String url = "";
    private static String user = "";
    private static String password = "";
    private static String className = "";
    static {
        try {
            Class.forName(className);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    // 得到連接
    public static Connection getConn() {
        @SuppressWarnings("unused")
        Connection conn = null;
        try {
            conn = DriverManager.getConnection(url, user, password);
        } catch (SQLException e) {

            e.printStackTrace();
        }

        return null;
    }

    // 关闭连接
    public static void close(ResultSet rs, Statement stm, Connection conn) {
        if (rs != null) {
            try {
                rs.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        if (stm != null) {
            try {
                stm.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }
}

现在主要是学习如何使用这个工具类。简单了解CURD的实现过程。

在百度百科中关于CURD是这样解释的:

CURD是一个数据库技术中的缩写词,一般的项目开发的各种参数的基本功能都是CURD。作用是用于处理数据的基本原子操作。

它代表创建(Create)、更新(Update)、读取(Retrieve)和删除(Delete)操作。

CURD 定义了用于处理数据的基本原子操作。.

之所以将CURD 提升到一个技术难题的高度是因为完成一个涉及在多个数据库系统中进行CRUD操作的汇总相关的活动,其性能可能会随数据关系的变化而有非常大的差异。

CURD 操作通常是使用关系型数据库系统中的结构化查询语句(Structured Query Language,SQL)完成的。随着 Web 变得更加具有面向数据特性,因此需要从基于 SQL 的 CURD 操作转移到基于语义 Web 的 CURD 操作。

呃,一言以蔽之——增删改查。

一、增加操作

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

//增加操作
public class Test3 {
    static int add(StuInfo stu) {
        int result = 0;

        Connection conn = null;
        Statement stm = null;

        try {
            conn = DBUtil.getConn();
            stm = conn.createStatement();
            String sql = "insert into stuInfo(name,age,shoolId) values(‘"
                    + stu.getName() + "‘," + stu.getAge() + ","
                    + stu.getSchoolId() + ")";// 字符串类型不要忘记加单引号
            result = stm.executeUpdate(sql);// 返回值代表数据库中受影响的行数
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            DBUtil.close(null, stm, conn);
        }
        return result;
    }

    public static void main(String[] args) {
        StuInfo stu = new StuInfo();
        stu.setName("阿三");
        stu.setAge("25");
        stu.setSchoolId(3);

        int result = add(stu);
        if (result > 0) { // 这里写result=1,编译通不过
            System.out.println("操作成功");
        } else {
            System.out.println("操作失败");
        }

    }
}

二、删除操作

//刪除操作
static int delStuById(int id){
    int result=0;
    Connection conn=null;
    Statement stm=null;

    try{
        conn=DBUtil.getConn();
        stm=conn.createStatement();
        String sql="delete from stuInfo where id=4"+id;
        result=stm.executeUpdate(sql);
    }catch(Exception e){
        e.printStackTrace();
    }finally{
        DBUtil.close(null,stm,conn)
    }
    return result;
}

三、更新操作

//更新操作
static int updateStudent(StuInfo stu) {
    int result = 0;
    Connection conn = null;
    Statement stm = null;
    try {
        conn = DBUtil.getConn();
        stm = conn.createStatement();
        String sql = "update stuInfo set name=‘" + stu.getName() + "‘,age="
                    + stu.getAge() + ",schoolId=" + stu.getSchoolId()
                    + " where id=" + stu.getId() + " ";
        result=stm.executeUpdate(sql);
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            DBUtil.close(null, stm, conn);
        }
    return result;
    }

四、查找操作

// 查询操作
    static StuInfo getStuById(int id){
        StuInfo stu=null;

        Connection conn=null;
        ResultSet rs=null;
        Statement stm=null;

        try{
            conn=DBUtil.getConn();
            stm=conn.createStatement();
            String sql="select * from stuInfo where id="+id;
            rs=stm.executeQuery(sql);
            if(rs.next()){
                stu=new StuInfo();
                stu.setId(rs.getInt("id"));
                stu.setName(rs.getString("name"));
                stu.setAge(rs.getInt("age"));
                stu.setSchoolId(rs.getInt("schoolId"));
            }

        }catch(Exception ex){
            ex.printStackTrace();
        }finally{
            DBUtil.close(rs,stm,conn);
        }

        return stu;
    }

查找出列表

//查询出列表
    public static List<StuInfo> getAllStudent(){
        List<StuInfo> stuList=new ArrayList<StuInfo>();

        Connection conn=null;
        ResultSet rs=null;
        Statement stm=null;

        try{
            conn=DBUtil.getConn();
            stm=conn.createStatement();
            String sql="select * from stuInfo " ;
            rs=stm.executeQuery(sql);
            while(rs.next()){
                StuInfo stu=new StuInfo();
                stu.setId(rs.getInt("id"));
                stu.setName(rs.getString("name"));
                stu.setAge(rs.getInt("age"));
                stu.setSchoolId(rs.getInt("schoolId"));

                stuList.add(stu);
            }

        }catch(Exception ex){
            ex.printStackTrace();
        }finally{
            DBUtil.close(rs,stm,conn);
        }

        return stuList;
    }

    public static void main(String[] args) {
        List<StuInfo> stuList=getAllStudent();
        for(int i=0;i<stuList.size();i++){
            System.out.println(stuList.get(i));
        }

    }

五、SQL 注入攻击

因为在给sql语句传参的时候,使用了字符串拼接的方式,所以导致了这种漏洞。

比如,注入串 :  1‘ or ‘1‘=‘1,使得密码安全性缺失。

解决:

String sql="select * from admininfo where userName =‘"+userName+"‘ and password=‘"+password+"‘ ";

六、PreparedStatement

在SQL中包含特殊字符或SQL的关键字(如: ‘ or 1 or ‘)时Statement将出现不可预料的结果(出现异常或查询的结果不正确),可用PreparedStatement来解决。

PreparedStatement 是 从 Statement 扩展来的

优点:

1) 解决sql注入攻击

2) Statement 会使数据库频繁编译sql,可能造成数据缓冲区溢出

3) 数据库和驱动,可以对 PreparedStatement 进行优化

代码示例:

// 防注入的登录
public static AdminInfo getLoginAdmin(String userName,String password){
    AdminInfo admin=null;
    Connection conn=null;
    ResultSet rs=null;
    PreparedStatement stm=null; //第一处

    try{
        conn=DBUtil.getConn();
        String sql="select * from adminInfo where userName=? and password=?" ; //第二处:改成占位符表示
        stm=conn.preparedStatement(sql);//第三处:注意,扩号里要传参,这条代码,要放在下面的两条之前
        stm.setString(1,userName);//地四处:传参
        stm.setString(2,password);

        rs=stm.executeQuery();//第五处:如果用preparedStatement,这里不要传参

        if(rs.next()){
            admin=new AdminInfo();
            admin.setId(rs.getInt("id"));
            admin.setUserName(rs.getString("userName"));
            admin.setPassword(rs.getString("password"));
            admin.setAddress(rs.getString("address"));
        }
    }catch(Exception e){
        e.printStackTrace();
    }finally{
        DBUtil.close(rs,stm,sonn);
    }
    return admin;
}

六、几种常见的特殊类型

1).DATA,TIME,TIMESTAMP-> date,time,datetime

存:stm.setDate(i,d); stm.setTime(i,t); stm.setTimestamp(i, ts);

取:rs.getDate("birthday"); rs.getTime(i); rs.getTimestamp(i);

2).CLOB -> text

存:ps.setCharacterStream(index, reader, length);

ps.setString(i, s);

取:reader = rs. getCharacterStream(i);

reader = rs.getClob(i).getCharacterStream();

string = rs.getString(i);

3).BLOB -> blob

存:ps.setBinaryStream(i, inputStream, length);

取:rs.getBinaryStream(i);

rs.getBlob(i).getBinaryStream

演示1:日期类型

//日期類型
//java.sql.Date是java.util.Date的子类
public static int add(AdminInfo admin){
    int result = 0;
    Connection conn = null;
    PreparedStatement stm = null;
    try {
        conn = DBUtil.getConn();
        String sql="insert into adminInfo (userName,password,address, createDate,birthday) values (?,?,?,?,?) ";
        stm = conn.prepareStatement(sql);
        stm.setString(1, admin.getUserName());
        stm.setString(2, admin.getPassword());
        stm.setString(3, admin.getAddress());
        //stm.setDate(4,admin.getCreateDate());//要的是子类,父类传不进去
        stm.setDate(4, new java.sql.Date(admin.getCreateDate().getTime()));  //可以用字符串类型处理data
        stm.setString(5, admin.getBirthday());
        result=stm.executeUpdate();
        } catch (Exception ex) {
            ex.printStackTrace();
            } finally {
                DBUtil.close(null, stm, conn);
                }
    return result;
    }
}
public static void main(String[] args) {
    AdminInfo admin=new AdminInfo();
    admin.setUserName("阿三");
    admin.setPassword("123");
    admin.setAddress("杭州文一西路");
    admin.setCreateDate(new Date());
    admin.setBirthday("1999-03-05 12:20:40");
    int result=add(admin);
    if(result>0){
        System.out.println("成功");
        }else{
            System.out.println("失败");
            }
    }

演示2:大文本处理

    //将c盘的文件  index.html 读入数据库
    static int addContent(){
        int result=0;
        Connection conn=null;
        PreparedStatement stm=null;
        try{
            conn=DBUtil.getConn();
            String sql="insert into t_testclob (content) values (?)";
            stm=conn.prepareStatement(sql);

            Reader br=new BufferedReader(new FileReader("c:\\index.html"));
            stm.setCharacterStream(1, br);

            result=stm.executeUpdate();

            br.close();

        }catch(Exception ex){
            ex.printStackTrace();
        }finally{
            DBUtil.close(null, stm, conn);
        }

        return result;
    }

演示3:读文件并保存到指定位置

      //把text类型的数据,读出来,存到e盘
        static void getContent(){
        Connection conn=null;
        PreparedStatement stm=null;
        ResultSet rs=null;
        try{
            conn=DBUtil.getConn();
            String sql="select * from t_testclob";
            stm=conn.prepareStatement(sql);
            rs=stm.executeQuery();

            while(rs.next()){
                BufferedReader r=new BufferedReader(rs.getCharacterStream("content")); 

                BufferedWriter bw=new BufferedWriter(new FileWriter("e:\\testxxx.txt"));
                String str=null;
                while((str=r.readLine())!=null){
                    bw.write(str);
                    bw.newLine();
                    bw.flush();
                }

                bw.close();
                r.close();
            }

        }catch(Exception ex){
            ex.printStackTrace();
        }finally{
            DBUtil.close(null, stm, conn);
        }
    }

演示4:从数据库中读取图片

public static void getPhoto(){
    ResultSet rs=null;
    Connection conn=null;
    PreparedStatement stm=null;
    try{
        conn=DBUtil.getConn();
        String sql="select * from t_testblob";
        stm=conn.prepareStatement(sql);
        rs=stm.executeQuery();

        int i=0;
        while(rs.next()){
            //    rs.getString("content");
            InputStream in=rs.getBinaryStream("photo");
            OutputStream out=new BufferedOutputStream(new FileOutputStream("e:\\test"+i++ +".bmp" ));
            byte [] buff=new byte[1024];
            int len=0;
            while((len=in.read(buff))!=-1){
                out.write(buff,0,len);
                }
            out.close();
            in.close();
            }
        }catch(Exception ex){
            ex.printStackTrace();
            }finally{
                DBUtil.close(rs, stm, conn);
                }
    }

演示5:读一副图片到数据库

public static int addPhoto(){
    int result=0;
    Connection conn=null;
    PreparedStatement stm=null;
    try{
        conn=DBUtil.getConn();
        String sql="insert into t_testblob (name,photo) values (?,?)";
        stm=conn.prepareStatement(sql); 

        InputStream in=new BufferedInputStream(new FileInputStream("c://bigPhoto.bmp")); 

        stm.setString(1, "大头鬼");
        stm.setBinaryStream(2,in);

        result=stm.executeUpdate();
        in.close();

    }catch(Exception ex){
        ex.printStackTrace();
        }finally{
            DBUtil.close(null, stm, conn);
            }
    return result;
    }

附加:

图象或二进制文件 (Blob)

在mysql中,叫blob,在sqlserver中,叫 image  普通的blob 是64k。如果文件超过1M,则出现

Packet for query is too large (3781053 > 1048576). You can change this value on the server by setting the max_allowed_packet variable.

解决:

mysql 有一个系统参数 max_allowed_packet 默认值是 1048576(1M),

在my.ini中 , 找到 max_allowed_packet 它的值默认是 1M,可以将这个值调大。

演示六:使用配置文件

//在 DBUtil中设置
private static String url;
private static  String user;
private static String password;
private static String className;
static{
    try {
        //读取配置文件
        Properties settings =new Properties();
        InputStream in=new FileInputStream("src/dbconfig.properties");
        settings.load(in);

        url=settings.getProperty("url");
        user=settings.getProperty("user");
        password=settings.getProperty("password");
        className=settings.getProperty("className");

        System.out.println(url);

        Class.forName(className); //加载驱动类  //如果不导jar包 Could not initialize class util.DBUtil

    } catch (ClassNotFoundException | IOException e) {//在Java核心基础1中介绍,可以这样做
        throw new RuntimeException(e);
        }
    }
时间: 2024-10-10 14:15:35

Java JDBC的基础知识(四)的相关文章

Java语言的基础知识12

第十四章(使用集合类保存对象) 1.java中得集合对象就像是一个容器,它用来存放Java类的对象.Java中的集合类有些方便存入和取出,有些则方便查找.集合类和数组的区别是,数组的长度是固定的,集合的长度是可变的,数组用来存放基本类型,集合用来存放对象的引用.常用的集合类有List集合,Set集合,和Map集合. 2.List集合包括List接口以及List接口的所有实现类.List集合中的元素许重复,个元素的顺序就是对象插入的顺序.类似java中的数组.List类继承了Collection接

Java语言的基础知识3

第四章 1.sum +=x++;的语句等价于sum=sum+x;和x=x+1;两条语句 2.do....while循环语句与while循环语句类似.他们之间的差别是while语句为先判断条件是否成立再执行循环体,而do...while循环语句是先执行一次循环体,在判断条件是否成立.也就是说do....while循环语句至少执行一次循环体. 3.在一个循环语句中又包含另外一个完整的循环语句,称为嵌套循环,笔者不建议使用超过3层的嵌套循环,因为这样会使程序更加难以阅读. 4.乘法口诀中用到的制表符"

Java的入门基础知识

https://course.tianmaying.com/java-basic%2Bjava-environment#0 作者:David链接:https://www.zhihu.com/question/25255189/answer/86898400来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 这个教程将Java的入门基础知识贯穿在一个实例中,逐步深入,可以帮助你快速进入Java编程的世界.万事开头难,逐步跟着这个教程走一遍,对Java应该就会有一种入门的

Java语言的基础知识

第三章 1.在java源文件编辑器中,选择某个成员变量,然后按住shift+alt+j,Eclipse会自动添加JavaDoc文档注释结构,如果选择的是方法,还会自动添加参数名称. 2.Java语言规定标示符是由任意的字母.下划线.美元符号和数字组成,并且第一个字符不能使数字,标示符不能使java中的保留关键字. 3.在Java语言中允许使用汉字或其他语言文字作为变量名,如int 年龄 =21;在程序运行时不会报错,但建议尽量不要使用这些语言作为变量. 4.java用关键字final来声明常量,

Java并发(基础知识)—— Executor框架及线程池

在Java并发(基础知识)—— 创建.运行以及停止一个线程中讲解了两种创建线程的方式:直接继承Thread类以及实现Runnable接口并赋给Thread,这两种创建线程的方式在线程比较少的时候是没有问题的,但是当需要创建大量线程时就会出现问题,因为这种使用方法把线程创建语句随意地散落在代码中,无法统一管理线程,我们将无法管理创建线程的数量,而过量的线程创建将直接使系统崩溃. 从高内聚角度讲,我们应该创建一个统一的创建以及运行接口,为我们管理这些线程,这个统一的创建与运行接口就是JDK 5的Ex

Java语言的基础知识4

第五章(数组) 1.在Java中可以将数组看做是一个对象虽然基本数据类型不是对象但有基本数据类型组成的数组是对象. 2.对于二维数组求第二维就用array[0].length, array.length就是默认的是第一维的长度. 3.foreach并不是一个新的语法它是for的循环的格式化主要执行遍历功能的循环,example: int arry ={1,2,3,4,5}; for(int i :array){ system.out.println(): } 4.数组元素定义完以后可通过Arra

黑马程序员——Java I/O基础知识之I/O流

I/O流基础知识--字节流和字符流 文件存储在硬盘中,是以二进制表示的,只有内存中才能形成字符.数据的来源可以有硬盘,内存,控制台,网络,Java把数据从一个地方转到另一个地方的现象称为流,用InputStream和OutputStream接口来表示,这两个流里面的都是以字节为单位的,后来加入了Reader和Writer,里面操作的是字符,是两个字节为单位的. 字节流 字节流将数据写入文件 try { File file =new File("d:" +File .separator+

C# 基础知识 (四).C#简介及托管代码

        暑假转瞬即逝,从10天的支教生活到1周的江浙沪旅游,在这个漫长的暑假中我经历了很多东西,也学到了很多东西,也认识到了很多不足之处!闲暇之余我准备重新进一步巩固C#相关知识,包括C#入门知识.C#并行开发.ASP网站等.这篇文章我介绍的是书籍--C#入门经典(Beginning C#) 作者Karli Watson.主要包括的是我自己缺乏的一些C#简介知识和托管代码的内容.内容比较简单,参照该书籍较多,相当于自己的在线笔记!                             

Java语言的基础知识10

第十二章(GUI事件) 1.GUI事件的处理机制是建立交互式应用程序的关键技术,其中事件是用在程序界面上的各种操作. 2.写程序的时候对于swing的一些空间譬如jprogressbar ,jtextfield等空间在全局中声明以后,用的时候一定要new 一下,自己经常忘记(由于对java理解不深) private  JTextField textField2; textField2 = new JTextField(); 3.事件在java语言中也是一种对象 4.监听器接受到事件之后,将委托指