Jdbc笔记(一)

本文深入探讨了数据库查询技术,包括复杂查询、报表查询等,以及JDBC编程在数据库操作中的应用,详细解释了JDBC编码步骤、数据库备份与恢复方法,最后介绍了如何使用PreparedStatement防止SQL注入,确保数据安全。

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

一、复杂查询
    1、连接查询
        连接查询的from子句的连接语法格式为:
        from TABLE1 join_type(表示下面的关键字) TABLE2  [on (join_condition)](可有可无) [where (query_condition)](可有可无)
        TABLE1:左表
        TABLE2:右表
 
        1.1交叉链接(cross join):(下面两句一样结果)
            SELECT * FROM customer CROSS JOIN orders;
            SELECT * FROM customer,orders;
        1.2内连接(inner join):
            显式内连接:使用inner join关键字和on(连接条件)
                 select o.order_number,o.price,c.name,c.city from orders o inner join customer c on o.customer_id=c.id;
                也可以写为:
                select o.order_number 订单号码,o.price 订单价格,c.name 客户,c.city 地址 from orders o inner join customer c on o.customer_id=c.id;
            隐式内连接:不使用inner join关键字,使用where(只能使用表达式)设置链接条件
                 select o.order_number,o.price,c.name,c.city from orders o,customer c where o.customer_id=c.id;
                也可以写为:
                select o.order_number 订单号码,o.price 订单价格,c.name 客户,c.city 地址 from orders o,customer c where o.customer_id=c.id;
        1.3外连接(outer join)
            左外链接(left):返回满足链接条件的数据,同时还返回左表中不满足条件的剩余记录。
                显示所有的订单(左表),如果有对应的客户(右表),把客户信息显示出来。(显示所有订单(左表),没有订单的客户(右表)不显示)
                select * from orders o left outer join customer c on o.customer_id=c.id;
            右外链接(right):
                显示所有的客户(右表),如果有订单(左表),把订单显示出来。(显示所有客户(右表),没有客户的订单(左表),不显示)
                select * from orders o right outer join customer c on o.customer_id=c.id;
    2、子查询:嵌套查询
        查询陈冠希的订单详情
        select id from customer where name='陈冠希';(需要先确认name为陈冠希的id)
        select * from orders where customer_id=1;(然后通过这个id来查找他的订单)
        //子查询,可以把以上两句命令嵌套在一起进行查询.
        select * from orders where customer_id=(select id from customer where name='陈冠希');
    3、联合查询(联合查询 union 关键字  把两条语句联合到一起,取并集)
        SELECT * FROM orders WHERE price>200 UNION SELECT * FROM orders WHERE customer_id=1;
            3   7                   1 2 3   UNION   1237
    4、报表查询(很重要,开发中经常出现);
[select …] from … [where…] [ group by … [having… ]] [ order by … ]
其中group by 子句指定按照哪些字段分组,having子句设定分组查询条件。
 
注意:  ---------------------
统计一个班级共有多少学生?
select count(*) from student;
select count(id) from student;//id是主键或者不为null,可以。
 
统计数学成绩大于90的学生有多少个?
select count(*) from student where math>=90;
 
统计总分大于250的人数有多少?
select count(*) from student where (chinese+english+math)>250;
统计一个班级数学总成绩?
select sum(math) from student;
统计一个班级语文、英语、数学各科的总成绩
select sum(chinese),sum(english),sum(math) from student;
统计一个班级语文、英语、数学的成绩总和
select sum(chinese+math+english) from student;
统计一个班级语文成绩平均分
select sum(chinese)/count(*) from student;
求一个班级数学平均分?
select avg(math) from student;
求一个班级总分平均分
select avg(chinese+math+english) from student;
-----------------------------------
Tips:如果使用数据库关键字作为普通名称,要使用``(与波浪线一个按键上的那个)引起来
对订单表中商品归类后,显示每一类商品的总价
select product,sum(price) from order1 group by product;//按照product分组,搜索的项目是product,sum(price)
查询购买了几类商品,并且每类总价大于100的商品:having必须跟在group by后面,对分组后的数据进一步的筛选。having可以使用统计函数。
select product,sum(price) from order1 group by product having sum(price)>100;
 count(1)  count(2)  查询结果一样,where 1=1,返回所有.
 如果使用数据库关键字作为普通名称使用,要用`order ` 引起来    esc按键下面的键
 group 不能使用where,使用having,可以使用统计函数,不能使用表达式
 
二、数据库备份与数据库恢复
1、数据库的备份:
shell>mysqldump -u root -psorry day10>e:/day10.sql
2、数据库的恢复:
前提:书库名称必须存在:create database day10;
方式一:
mysql>use DAY10;
mysql>source e:/day10.sql;
方式二:(系统命令行下)
shell>mysql -u root -psorry day10<e:/day10.sql
 
注意命令中如果\的话,表示制表符,所以要用/.
shell就是window或者Linux   系统
 
 
 
三、JDBC简介
    JDBC全称为:Java Data Base Connectivity(java数据库连接),它主要由接口组成。
    JDBC属于JavaEE技术之一。它的API类在JDK中。是SUN公司制定的规范
    数据库厂商就对JDBC进行了实现,所谓的驱动。
 
    java.sql.*
    javax.sql.*
 
    开发环境:JDBC+数据库对应的驱动
 
四、JDBC编码步骤
1、注册驱动
不能直接new一个com.mysql.jdbc.Driver,
//DriverManager.registerDriver(new com.mysql.jdbc.Driver());
因为这样1、依赖具体的数据库驱动;2、会导致驱动被注册2遍.
Class.forName("com.mysql.jdbc.Driver");
 
2、获取与数据库的连接
//方式一:
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day10""root""sorry");
//方式二:
Properties props = new Properties();
props.put("user""root");//key看数据库的规定
props.put("password""sorry");
props.put("useUnicode""true");
props.put("characterEncoding""utf8");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day10", props);
//方式三:
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day10?user=root&password=sorry");
注意,数据库的URL需要查看相关文档,不同数据库不同版本,URL都不一定一样.
URL:   协议(jdbc):子协议(mysql):主机:端口/数据库
 
3、得到代表SQL语句的对象
Statement stmt = conn.createStatement();
 
4、发送SQL语句:DML、DQL
ResultSet rs = stmt.executeQuery("selcet chinese,english,math from student");
//Statement常用方法
//ResultSet executeQuery(String sql):sql一般是DQL语句
//int executeUpdate(String sql):sql一般是没有返回结果集的语句,比如DML、DDL。返回值是影响到的行数
//boolean execute(String sql):sql可以任何的语句。返回值:如果执行的sql语句有结果集,返回true,没有结果集,返回false
 
5、如果是DQL语句,有结果,得到返回的结果
 
6、遍历结果集
while(rs.next()){
    System.out.println("---------------------------");
    System.out.print(rs.getObject("chinese")+"\t");
    System.out.print(rs.getObject("english")+"\t");
    System.out.println(rs.getObject("math"));
}
 
7、释放占用的资源(官方文档,最好写成工具类.)
//JDBC工具类
public class JdbcUtil {
    private static String driverClass;
    private static String url;
    private static String user;
    private static String password;
    
    static{
        try {
            //从配置文件中读取信息
            InputStream in = JdbcUtil.class.getClassLoader().getResourceAsStream("dbcfg.properties");
            Properties pro = new Properties();
            pro.load(in);
            driverClass = pro.getProperty("driverClass");
            url = pro.getProperty("url");
            user = pro.getProperty("user");
            password = pro.getProperty("password");
            
            Class.forName(driverClass);
        } catch (Exception e) {
            throw new ExceptionInInitializerError(e);
        }
    }
    
    public static Connection getConnection() throws Exception {
        return DriverManager.getConnection(url,user,password);
    }
    
    public static void release(ResultSet rs,Statement stat,Connection conn){
        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            rs = null;
        }
        if(stat!=null){
            try {
                stat.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            stat = null;
        }
        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            conn = null;
        }
    }
}
 
五、JDBC中常用接口详解
    DriverManager:
        注册驱动
        获取数据库的链接
 
六、JDBC对数据库中的数据进行CRUD,增删改查
    public void testInsert(){
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            conn = JdbcUtil.getConnection();
            stmt = conn.createStatement();
            stmt.executeUpdate("insert into users (name,password,email,birthday) values('任敏','123','rm@itheima.com','1989-09-19')");
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            JdbcUtil.release(rs, stmt, conn);
        }
        
    }
    public void testUpdate(){
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            conn = JdbcUtil.getConnection();
            stmt = conn.createStatement();
            stmt.executeUpdate("update users set password='1234' where id=6");
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            JdbcUtil.release(rs, stmt, conn);
        }
    }
    public void testDelete(){
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            conn = JdbcUtil.getConnection();
            stmt = conn.createStatement();
            for(int x=8;x<10;x++)
            stmt.executeUpdate("delete from users where id="+x);
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            JdbcUtil.release(rs, stmt, conn);
        }
 
七、用MySQL来改写原来的用户注册和登陆案例
    public void addUser(User user) {
        Connection conn = null;
        Statement stmt = null;
        try {
            conn = JdbcUtil.getConnection();
            stmt = conn.createStatement();
            stmt.executeUpdate("insert into user (username,nick,password,email,birthday) values('"+user.getUsername()+"','"+user.getNick()+"','"+user.getPassword()+"','"+user.getEmail()+"','"+user.getBirthday().toLocaleString()+"')");
        } catch (Exception e) {
            throw new DaoException(e);
        }finally{
            JdbcUtil.release(null, stmt, conn);
        }
    }
    public User findUser(String username, String password) {
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            conn = JdbcUtil.getConnection();
            stmt = conn.createStatement();
            String str = "select username,nick,password,email,birthday from user where username='"+username+"' and password='"+password+"'";
            rs = stmt.executeQuery(str);
            if(rs.next()){
                User user = new User();
                user.setUsername(rs.getString("username"));
                user.setNick(rs.getString("nick"));
                user.setPassword(rs.getString("password"));
                user.setEmail(rs.getString("email"));
                user.setBirthday(rs.getDate("birthday"));
                return user;
            }else{
                return null;
            }
        } catch (Exception e) {
            throw new DaoException(e);
        }finally{
            JdbcUtil.release(rs, stmt, conn);
        }
    }
 
八、PreparedStatement:日后都用它
SQL 注入是用户利用某些系统没有对输入数据进行充分的检查,从而进行恶意破坏的行为。
1、statement存在sql注入攻击问题,例如登陆用户名采用' or 1=1 or name='
2、对于防范 SQL 注入,可以采用PreparedStatement取代Statement。
 
    它是Statement的子接口
    作用:
        支持预编译SQL:执行效率高。Statement是先编译,然后执行.而这个类创建之初就会编译SQL语句,虚拟机直接运行
        支持参数占位符:?
        防止SQL注入
public void addUser(User user) {
    Connection conn = null;
    PreparedStatement stmt = null;
    try{
        conn = JdbcUtil.getConnection();
        stmt = conn.prepareStatement("insert into user (username,nick,password,email,birthday) values (?,?,?,?,?)");
        stmt.setString(1, user.getUsername());
        stmt.setString(2, user.getNick());
        stmt.setString(3, user.getPassword());
        stmt.setString(4, user.getEmail());
        //这里的Date不能向下转型,子类的实例对象可以转成父类,但是父类的实例对象不能转成子类
        stmt.setDate(5, new java.sql.Date(user.getBirthday().getTime()));
        //记住,这里还需要插入动作.
        stmt.executeUpdate();
    }catch(Exception e){
        throw new DaoException(e);
    }finally{
        JdbcUtil.release(null, stmt, conn);
    }
}
 
九、DAO解耦
把控制权转移到外面,想要创建对象,必须先传参数依赖注入
public void setDao(User dao){
this.dao = dao;
{
另一种方式通过构造函数转过来
单开就是  单例设计模式
    //到底使用哪一个,是由自己指定的。是new出来的,没法解耦    
    //如果由外部传入使用的实现类,这个过程称之为控制反转,就可以解耦了.IoC DI:依赖注入:Spring的核心
    //工厂创建模式,就是把创建的细节隐藏起来.
    private UserDao dao = DaoFactory.getInstance().getUserDaoImpl();// = new UserDaoMySQLEnhanceImpl();
//    public UserServiceImpl(UserDao dao){//依赖注入方法一,通过构造方式
//        this.dao = dao;
//    }
//    public void setDao(UserDao dao){//依赖注入方式二,通过set方法
//        this.dao = dao;
//    }
//创建DAO实例的工厂:饿汉子式单例
public class DaoFactory {
    //先创建工厂类,需要私有化,为了能一家在就实例化,需要静态修饰
    private static DaoFactory instance = new DaoFactory();
    //无参构造函数私有化
    private DaoFactory(){}
    //定义静态方法,调用类
    public static DaoFactory getInstance(){
        return instance;
    }
    //私有Properties类,
    private static Properties props = new Properties();
    static{
        //静态代码块,初始化就加载,这样就参数就可以使用字符串,就可以写到配置文件中.
        InputStream in = DaoFactory.class.getClassLoader().getResourceAsStream("dao.properties");
        try {
            props.load(in);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    //创建一个UserDaoImpl实例类,需要的参数读取配置文件
    //这样就进行了解耦,所有需要的参数可以通过修改配置文件来完成
    public UserDao getUserDaoImpl(){
        try {
            String daoImplName = props.getProperty("userDao");
            return (UserDao)Class.forName(daoImplName).newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
十、大数据(大文本和大二进制)存取
 
、概述: JDBC从物理结构上说就是Java语言访问数据库的套接口集合。从本质上来说就是调用者(程序员)和实现者(数据库厂商)之间的协议。JDBC的实现由数据库厂商以驱动程序的形式提供。JDBC API 使得开发人员可以使用纯Java的方式来连接数据库,并进行操作。 ODBC:基于C语言的数据库访问接口。 JDBC也就是Java版的ODBC。 JDBC的特性:高度的致性、简单性(常用的接口只有4、5个)。 1.在JDBC中包括了两个包:java.sql和javax.sql。 ① java.sql 基本功能。这个包中的类和接口主要针对基本的数据库编程服务,如生成连接、执行语句以及准备语句和运行批处理查询等。同时也有些高级的处理,比如批处理更新、事务隔离和可滚动结果集等。 ② javax.sql 扩展功能。它主要为数据库方面的高级操作提供了接口和类。如为连接管理、分布式事务和旧有的连接提供了更好的抽象,它引入了容器管理的连接池、分布式事务和行集等。 注:除了标出的Class,其它均为接口。 API 说明 java.sql.Connection 与特定数据库的连接(会话)。能够通过getMetaData方法获得数据库提供的信息、所支持的SQL语法、存储过程和此连接的功能等信息。代表了数据库。 java.sql.Driver 每个驱动程序类必需实现的接口,同时,每个数据库驱动程序都应该提供个实现Driver接口的类。 java.sql.DriverManager (Class) 管理JDBC驱动程序的基本服务。作为初始化的部分,此接口会尝试加载在”jdbc.drivers”系统属性中引用的驱动程序。只是个辅助类,是工具。 java.sql.Statement 用于执行静态SQL语句并返回其生成结果的对象。 java.sql.PreparedStatement 继承Statement接口,表示预编译的SQL语句的对象,SQL语句被预编译并且存储在PreparedStatement对象中。然后可以使用此对象高效地多次执行该语句。 java.sql.CallableStatement 用来访问数据库中的存储过程。它提供了些方法来指定语句所使用的输入/输出参数。 java.sql.ResultSet 指的是查询返回的数据库结果集。 java.sql.ResultSetMetaData 可用于获取关于ResultSet对象中列的类型和属性信息的对象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值