java学习笔记(jdbc):

这篇博客主要介绍了Java中JDBC的概念,包括入门的七大步骤和API解析,特别讲解了PreparedStatement的使用及其与Statement的区别。此外,还探讨了代码封装的最佳实践和注解的基本概念及类型分类。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.jdbc

    1)概念:

JDBC:Java连接数据库 ,使用Java语言规范 操作数据库.

    2)jdbc的入门七大步骤_设计的API解释说明:

1)导入数据库包 mysql-connector-java-8.0.23.jar  mysql8的jar包
    有了包了,里面的核心类就加载进来了
2)注册驱动


    本身注册驱动:DriverManger里面
    public static void registerDriver(Driver driver) 注册驱动的方法

    推荐:
        加载类--->执行原码的静态代码块注册驱动
        Class.forName("com.mysql.cj.jdbc.Driver") ;---->获取com.mysql.cj.jdbc.Driver的类字节码文件对象
        向下兼容性

        原码的内容
            class com.mysql.cj.jdbc.Driver implements java.sql.Drvier{

                //静态代码块---本身就使用了DriverManger里面的注册驱动方法
                 static {
                        try {
                            java.sql.DriverManager.registerDriver(new Driver()); //本身就在注册驱动,不需要在单独写了
                        } catch (SQLException E) {
                            throw new RuntimeException("Can't register driver!");
                        }
                    }

            }
3)获取连接对象
  驱动管理程序的类DriverManager:
  Connection conn = DriverManager.getConnection(
                "jdbc:mysql://localhost:3306/javaee_2110?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true",  /
                                                                    //当前支持的字符集格式 服务器时区 开启公钥
                  "root",
                  "123456");)

java.sql.DriverManager:用于管理一组JDBC驱动程序的基本服务
           获取数据库的连接对象
                public static Connection getConnection(String url, String user, String password)
                参数1:统一资源定位符号
                    url组成
                        协议   :jdbc的协议  格式 ---> jdbc:    (java连接数据库)
                        数据库: mysql  /oracle  /指定的数据库 (安装特定数据库的服务器软件)
                        域名:端口号
                           本地 localhost:本机/或者直接写127.0.0.1:本地回环地址
                           远程连接
                                    远程服务器的ip地址或者域名

                           mysql端口号:3306

                        资源地址(数据库地址): 数据库名称

                 参数2:本地mysql的用户名 root
                 参数3:用户密码


           返回值类型:java.sql.Connection接口:与特定数据库的连接会话

4)准备sql
         String sql = "insert into student values(9,'德邦',18,'男','艾欧尼亚',60,70)";  静态sql   (硬编码)
5)通过连接对象创建执行对象
        java.sql.Connection:与特定数据库的连接会话
                Statement createStatement():创建执行对象,它可以将静态sql语句发送到数据库中
6)执行sql语句
    java.sql.Statement接口
            通用的方法
                int executeUpdate(String sql):将sql语句发送的数据库中执行 (更新操作)
                针对DDL:表的修改、创建、删除、查询。。。
                针对DML语句:insert into,update ,delete,

                ResultSet executeQuery(String sql):将select语句发送到到数据中进行执行(通用查询操作)

java.sql.ResultSet接口:
        数据库结果集的数据表,通常通过执行查询数据库的语句生成。

    3)案例:

 实现步骤
 *  1)导包--->jar包 mysql驱动jar包
 *  2)注册驱动
 *  3)获取数据库的连接对象
 *  4)准备好sql语句
 *  5)通过连接对象创建执行对象Statement   createStatement不安全 
                                               prepareStatement  安全推荐使用
 *  6)执行sql语句
 *  7)释放资源
 */
public class JdbcDemo {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {

            //1)导包--->jar包 mysql驱动jar包
            //2)注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver"); //mysql8的驱动的实现类的路径带cj这个包
            
            //3)获取数据库的连接对象
            //驱动管理程序的类DriverManager:
            //public static Connection getConnection(String url,  // url:连接数据库的地址:
            //String user, 数据库的用户名
            // String password) 密码 throws SQLException
            Connection conn = DriverManager.getConnection(
            //url:数据库后面? 一堆参数 mysql5.7以后
            "jdbc:mysql://localhost:3306/javaee_2110?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true",  //
            "root",
            "123456");
            // 4)准备好sql语句
            String sql = "insert into student values(9,'德邦',18,'男','艾欧尼亚',60,70)";
            //5)通过连接对象创建执行对象Statement
            //Statement createStatement()
            Statement stmt = conn.createStatement();
            //6)执行sql语句:通用方法:增删改
            //int executeUpdate(String sql)
            int count = stmt.executeUpdate(sql);
            System.out.println("影响了"
                            + count + "行");
            //7)释放资源
            stmt.close();//执行对象
            conn.close(); //连接对象
    }
}

1)PreparedStatement执行对象:

PreparedStatement执行对象:
 *    Connection接口:
 *       PreparedStatement prepareStatement(String sql):获取预编译对象,
                   同时将参数化的sql发送给数据库
 *         通过预编译的sql语句对象,它的内存中就可以对参数?(占位符)进行赋值

3)PreparedStatement和Statement区别:

Statement:执行静态sql语句,写死了---存在字符串拼接
          会造成SQL注入,是一种非常严重的问题,开发中不会使用Statement作为执行对象!
PreparedStatement
    最大的特点:参数化的sql,防止参数的字符串拼接,有效防止SQL注入,比Statement更安全

4)代码封装:

public class DeptTool {
    //定义私有化静态
    private static String driverName = null;
    private static String url = null;
    private static String uers = null;
    private static String password = null;
    //无参构造私有化
    private DeptTool() { }
    static {
        //创建一个空的properties属性集合列表
        Properties properties = new Properties();
        //获取src下的配置文件
        InputStream res = DeptTool.class.getClassLoader().getResourceAsStream("jdbc.properties");
        try {
            //将资源流的内容加载到属性列表中
            properties.load(res);
            //通过键过取值
            driverName = properties.getProperty("DriverName");
            url = properties.getProperty("url");
            uers = properties.getProperty("uers");
            password = properties.getProperty("password");
            //注册驱动
            Class.forName(driverName);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    //封装获取数据库的连接对象
    public static Connection getConnection(){
        Connection connection = null;
        try {
            connection = DriverManager.getConnection(url,uers,password);
            return connection;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }
    //针对DQL语句 释放资源封装
    //ResultSet Statement Connection
    public static void close(ResultSet res, Statement sta, Connection con){
        if(res != null){
            try {
                res.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (sta != null){
            try {
                sta.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (con != null){
            try {
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    //针对DDL DML语句释放资源封装
    public static void close( Statement sta,Connection con){
        close(null,sta,con);
    }
}
--------------------------------------
public class Dept {
    private int id ;
    private String edept_name ;
    private String dept_address;

    public Dept() {
    }

    public Dept(int id, String edept_name, String dept_address) {
        this.id = id;
        this.edept_name = edept_name;
        this.dept_address = dept_address;
    }

    public int getId() {
        return id;
    }

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

    public String getEdept_name() {
        return edept_name;
    }

    public void setEdept_name(String edept_name) {
        this.edept_name = edept_name;
    }

    public String getDept_address() {
        return dept_address;
    }

    public void setDept_address(String dept_address) {
        this.dept_address = dept_address;
    }

    @Override
    public String toString() {
        return "Dept{" +
                "id=" + id +
                ", edept_name='" + edept_name + '\'' +
                ", dept_address='" + dept_address + '\'' +
                '}';
    }
}

-------------------------------------------------------------------
public interface DeptDemo {
        //分页查询
        List<Dept> limit(int indenx,int value);
        //添加整行
        void alter(Dept d);
        //删除整行
        void drop(int a);
        //查询整行
        Dept from(int b);
}
------------------------------------------------------------------
public class DeptDemoImpl implements DeptDemo{

    @Override
    public List<Dept> limit(int indenx, int value) {
        //获取对象连接
        Connection con = null;
        con= DeptTool.getConnection();
        PreparedStatement pre = null;
        ResultSet res = null;
        //准备SQL举例
        String sql = "SELECT * FROM dept LIMIT ? ,?;";
        List<Dept>  list  = new ArrayList<>();
        //获取执行对象
        try {
            pre = con.prepareStatement(sql);
            pre.setInt(1,indenx);
            pre.setInt(2,value);
            res = pre.executeQuery();
            Dept dept = null;
            while(res.next()){
                int anInt = res.getInt(1);
                String string = res.getString(2);
                String string1 = res.getString(3);
                dept = new Dept(anInt,string,string1);
                list.add(dept);
            }
            return list;
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DeptTool.close(res,pre,con);
        }
        return null;
    }
    @Override
    public void alter(Dept d) {
        //获取数据库连接对象
        Connection connection = null;
        PreparedStatement pre = null;
        connection = DeptTool.getConnection();
        //准备SQL语句
        String sql = "INSERT INTO dept VALUES (?,?,?);";
        try {
            //获取执行对象
            pre = connection.prepareStatement(sql);
            pre.setInt(1,d.getId());
            pre.setString(2,d.getEdept_name());
            pre.setString(3,d.getDept_address());
            pre.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DeptTool.close(pre,connection);
        }
    }

    @Override
    public void drop(int a) {
        //连接数据库
        Connection connection = null;
        PreparedStatement ment = null;
        connection = DeptTool.getConnection();
        //准备SQL语句
        String sql = "DELETE FROM dept  WHERE id = ?;";
        //创建执行对象
        try {
            ment = connection.prepareStatement(sql);
            ment.setInt(1,a);
            int i = ment.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //释放资源
            DeptTool.close(ment,connection);
    }
}

    @Override
    public Dept from(int b) {
        //连接数据库
        Connection con = null;
        PreparedStatement prepared = null;
        con = DeptTool.getConnection();
        //准备SQL语句
        String sql = "select *FROM dept  WHERE id = ?;";
        Dept dept = null;
        ResultSet result = null;
        //执行对象
        try {
            prepared = con.prepareStatement(sql);
            prepared.setInt(1,b);
                result = prepared.executeQuery();
            dept = new Dept();
            while (result.next()){
                String str = result.getString(2);
                String str1 = result.getString(3);
                dept.setId(b);
                dept.setEdept_name(str);
                dept.setDept_address(str1);
            }
            return dept;
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {

            DeptTool.close(result,prepared,con);
        }
        return null;
    }
}
------------------------------------------------
public class DeptTest {
    public static void main(String[] args) {
        //分页
       limit();
       alter();
       drop();
      from();
    }

    public static void limit(){
        DeptDemoImpl deptDemo = new DeptDemoImpl();
        List<Dept> m = deptDemo.limit(0, 2);
        for (Dept l : m){
            System.out.println(l);
        }
    }
    public static void alter(){
        Dept dept = new Dept(4,"DEVELOPMENT","China");
        DeptDemoImpl deptDemo = new DeptDemoImpl();
        deptDemo.alter(dept);
    }
    public  static void drop(){
        DeptDemoImpl deptDemo = new DeptDemoImpl();
        deptDemo.drop(50);
    }
    private static void from() {
        DeptDemoImpl deptDemo = new DeptDemoImpl();
        Dept from = deptDemo.from(2);
        System.out.println(from);
    }

}

4)五大步骤:

commons-dbtuls开源工具类库:对jdbc简易封装,简化书写代码!
下载地址:https://commons.apache.org/proper/commons-dbutils/ 官网


1)导包
        数据库驱动jar包
        druid连接池的包
        junit的包以及依赖包
        commons-dbtuls的包

             commons-dbutils-1.7.jar  核心包
             commons-lang-2.6.jar 语言包
             commons-logging-1.2.jar 日志包 ---后期使用log4j.properties:日志记录文件
             commons-collections-3.2.2.jar


2)配置文件 jdbc.properties:里面提供的数据库的连接参数(里面的名称不能写)以及连接池的参数
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/javaee_2110?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
username=root
password=123456
initialSize=5
maxActive=10
maxWait=3000
minIdle=3
maxIdle=4


3)书写实体类 com.qf.pojo
                Student

4)书写数据库的接口
            com.qf.dao
                    StudentDao
5)com.qf.dao.impl
                    StudentDaoImpl
                            实现

                   这里使用Dbutils工具的核心类
                   创建执行对象QueryRunner

5)案例:

自定义工具类
 *      获取连接对象
 *      获取数据源:DataSource
 */
public class DruidJbdcUtils {
    //线程 存储Connection:模拟线程
    private static ThreadLocal<Connection> t1 = new ThreadLocal<>() ;
    private static DataSource ds ;
    //静态代码块
    static{
        try {
            //加载druid.properties配置文件
            Properties prop = new Properties() ;
            //读取当前druid.properties里面的内容,获取到它所在的资源文件输入流对象
            InputStream inputStream = DruidJbdcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
            //加载属性列表中
            prop.load(inputStream) ;
            //创建数据源对象
             ds = DruidDataSourceFactory.createDataSource(prop); //获取数据源
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //定义静态功能,获取数据源
    public static DataSource getDataSource(){
        return ds ;
    }
    //获取连接对象
    //连接对象每一个现在模拟线程:用户都要连接对象,将连接对象:存储ThreadLocal
    public static Connection getConnetion(){
        Connection conn = null ;
        //先从线程ThreadLocal获取当前里面的连接对象
        //get():获取当前线程所在的连接对象
        try {
            conn = t1.get();
            if(conn == null ){
                //如果当前线程没有没有连接对象
                //从数据库连接池中获取
                 conn = ds.getConnection(); //从数据源(连接池)中获取连接对象,将连接对象绑定当当前线程上
                //绑定当前当线程上
                t1.set(conn);
            }
            return  conn ;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return  null ;
    }
    //封装释放资源代码
    //针对DQL语句操作,释放资源
    //ResuletSet,Statement,Connection
    public static void close(ResultSet rs, Statement stmt, Connection conn){
        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(stmt!=null){
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    // 将释放资源也可以封装到功能中
    //针对的是DDL/DML语句操作时释放资源
    public static void close(Statement stmt,Connection conn){
        close(null,stmt,conn);
    }

    //后期需要用到事务
    //封装事务的代码
    //开启事务
    public static void startStransaction() throws SQLException {
        Connection connection = ds.getConnection();
        connection.setAutoCommit(false) ; //禁用自动提交
        //释放资源
        connection.close() ; //归还到连接池中
        //需要从线程中解绑
        t1.remove();
    }
    //事务回滚
    public static void rollBackAndClose() throws SQLException {
        Connection connection = ds.getConnection();
        connection.rollback() ;//事务回滚
        //释放资源
        connection.close() ; //归还到连接池中
        //需要从线程中解绑
        t1.remove();
    }
    //提交事务
    public static void commitAndClose() throws SQLException {
        Connection connection = ds.getConnection();
        connection.commit(); ;//提交事务
        //释放资源
        connection.close() ; //归还到连接池中
        //需要从线程中解绑
        t1.remove();
    }
    public static void main(String[] args) {
        DataSource dataSource = DruidJbdcUtils.getDataSource();
        System.out.println(dataSource);
        Connection connetion = DruidJbdcUtils.getConnetion();
        System.out.println(connetion);
    }
}
----------学生的数据接口层--------------------
* 针对学生的数据接口层
 */
public interface StudentDao {

    /**
     * 查询所有学生信息
     * @return 返回的学生列表
     */
    List<Student> findAllStudent() throws SQLException;
    /**
     * 通过学生的编号获取学生信息
     * @param id  学生编号
     * @return 返回的就是学生实体
     * @throws SQLException
     */
    Student findStudentById(int id) throws  SQLException ;

    /**
     * 添加学生数据
     * @param student
     */
    void addStudent(Student student) throws SQLException;


    /**
     * 获取总记录数
     * @return
     */
    int  getTotalCount() throws SQLException;


}
--------------------------Dbutils工具类实现-----------------------------
 * 使用Dbutils工具类实现
 *
 *      QueryRunner对象
 *
 *          query(String sql...)
 *          update(String sql,Object...params)
 */
public class StudentDaoImpl implements StudentDao {
    /**
     * 查询所有学生数据
     * @return  列表
     * @throws SQLException
     */
    @Override
    public List<Student> findAllStudent() throws SQLException {
        //默认自动提交:创建执行对象

        //public QueryRunner(DataSource ds)
        QueryRunner qr = new QueryRunner(DruidJbdcUtils.getDataSource()) ; //同时加载数据源
        //书写sql
        String sql = "select * from student" ;
        //通用的查询方法
        //public <T> T query(String sql, ResultSetHandler<T> rsh, Object... params)
        //参数1:sql语句
        //参数2:查询的结果处理的接口 ResultSetHandler
        //public class BeanListHandler<T> implements ResultSetHandler<List<T>>
        //将ResultSet中所有的数据转化成List,List中存放的是类对象
        //参数3:params 实际参数
        List<Student> list = qr.query(sql, new BeanListHandler<Student>(Student.class));
        return list;
    }
    /**
     * * 通过学生的编号获取学生信息
     * @param id  学生编号
     * @return 返回的就是学生实体
     * @throws SQLException
     */
    @Override
    public Student findStudentById(int id) throws SQLException {
        //创建执行对象
        QueryRunner qr = new QueryRunner(DruidJbdcUtils.getDataSource()) ;

        //准备sql
        String sql  = "select * from student where id = ?" ;
        //执行查询
        //将查询某一条记录,封装到一条实体中
        //public <T> T query(String sql, ResultSetHandler<T> rsh, Object... params)
        //参数1:sql语句
        //参数2:查询的结果处理的接口 ResultSetHandler

        //public class BeanHandler<T> implements ResultSetHandler<T>
        //将ResultSet中查询的某一一行的数据转化成类对象
        Student student = qr.query(sql, new BeanHandler<Student>(Student.class), id);
        //不需要释放资源
        return student;
    }

    /**
     * 添加学数据
     * @param student
     */
    @Override
    public void addStudent(Student student) throws SQLException {
        //执行对象
        QueryRunner qr = new QueryRunner(DruidJbdcUtils.getDataSource()) ;
        //sql

        String sql = "insert into student values(?,?,?,?,?,?,?)" ;
        //通用的更新操作
        //public int update(String sql, Object... params) throws SQLException {}:针对增删改
        int count = qr.update(sql, student.getId(),
                student.getName(),
                student.getAge(),
                student.getSex(),
                student.getAddress(),
                student.getMath(),
                student.getEnglish());
        System.out.println(count);

    }

    /**
     * 查询总记录数
     * @return
     */
    @Override
    public int getTotalCount() throws SQLException {
        //执行对象
        QueryRunner qr = new QueryRunner(DruidJbdcUtils.getDataSource()) ;
        //sql
        String sql = "select count(id) from student" ;

        //将查询某一条记录,封装到一条实体中
        //public <T> T query(String sql, ResultSetHandler<T> rsh, Object... params)
        //参数1:sql语句
        //参数2:查询的结果处理的接口 ResultSetHandler
        //public class ScalarHandler<T> implements ResultSetHandler<T>
        //将ResultSet中一条记录的其中某一列的数据存成Object
        // public ScalarHandler()
        Object obj = qr.query(sql, new ScalarHandler<>());
        String strObj = String.valueOf(obj);
        //String---Int
        int count = Integer.parseInt(strObj);
        return count;
    }
}
-------------------单元测试类-----
 * @author Kuke
 * @date 2021/11/8 14:44
 */
public class StudentTest {

    @Test
    public void testFindAll() throws SQLException {
        StudentDao sd = new StudentDaoImpl() ;
        List<Student> list = sd.findAllStudent();
        if(list!=null){
            for(Student s:list){
                System.out.println(s);
            }
        }
    }

    @Test
    public void testStudentById() throws SQLException {
        StudentDao sd = new StudentDaoImpl() ;
        Student student = sd.findStudentById(5);

        System.out.println(student);
    }

    //测试添加
    @Test
    public void testAdd() throws SQLException {
        StudentDao sd = new StudentDaoImpl() ;
        Student student = new Student() ;
        student.setId(11) ;
        student.setName("孙杰") ;
        student.setAge(20) ;
        student.setSex("男");
        student.setAddress("西安市");
        student.setMath(89);
        student.setEnglish(90);
        sd.addStudent(student);

    }

    //测试查询总记录数
           @Test
        public void testgetCount() throws SQLException {
            StudentDao sd = new StudentDaoImpl() ;

               int totalCount = sd.getTotalCount();
               System.out.println(totalCount);

           }
}

5)注解:

     1)注解概念:

标记类,方法,参数,成员变量,由一种特殊的含义 (能被解析的)

    2)注解有哪些类型:

注解中的属性(方法名)---返回值类型  (5种 类型!)
*        String
*           枚举类型Enum
*           注解类型@Annotation
*           基本类型
*           以上类型的数组

    3)注解的分类

注解的分类
 *      jdk内置注解
 * @Overrid:标记当前这个方法是否为重写方法: 重写了类/抽象类或者接口
 * @Deprecated:标记某个方法是过时方法
 * @SuppressWarnings:压制警告, 一般企业中, 项目部署上线的时候,代码中不能黄色警告线!
 * @FunctionalInteface:函数式接口 :jdk8后,
 *      接口如果一个抽象方法,那么这个接口就可以是函数式接口----使用lambda表达式
 *
 *  内置注解底层依赖的元注解
 *       @Target(ElementType.METHOD)
 *              标记当前这个注解所作用的范围
 *              属性:
 *                  ElementType[] values()--->返回值枚举的数组--->里面一些常量
 *                          TYPE,当前注解可以作用在类上
 *
 *
 *                          FIELD,当前这个注解可以作用成员属性上

                            METHOD,  ...当前这个注解可以作用在方法上
 *
 *       @Retention(RetentionPolicy.SOURCE) :
 *              当做标记@Override注解的保留的阶段
 *                       RetentionPolicy value();
 *
 *                              返回值枚举类型
 *                                      SOURCE :原码编译阶段
 *                                      CLASS: 类 的加载
 *                                      RUNTIME:运行阶段

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值