数据库连接池

数据库连接池

  • 概念: 其实就是一个容器(集合),存放数据库连接的容器。当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后,会将连接对象归还给容器。

  • 好处:

    1. 节约资源
    2. 用户访问高效
  • 实现:

    1. 标准接口:DataSource

      1. 方法:
        • 获取连接:getConnection()
        • 归还连接:Connection.close()。如果连接对象Connection是从连接池中获取的,那么调用Connection.close()方法,则不会再关闭连接了,而是归还连接。
    2. 一般我们不去实现它,有数据库厂商来实现

      1. C3P0:数据库连接池技术。
      2. Druid:数据库连接池技术,由阿里巴巴提供。

C3P0:数据库连接池技术

  • 步骤:
    1. 导入jar包(两个) c3p0-0.9.5.5-sources.jar和mchange-commons-java-0.2.19-sources.jar
    2. 定义配置文件:
      • 名称:c3p0.properties或者c3p0-config.xml
      • 路径:直接将文件放在src目录下即可
    3. 创建核心对象:数据库连接池对象 ComboPooledDataSource
    4. 获取连接:getConnection

Druid:数据库连接池技术,由阿里巴巴提供

  • 步骤:

    1. 导入jar包 druid-1.1.22.jar
    2. 定义配置文件:
      • 是properties形式的
      • 可以叫任意名称,可以放在任意目录下
    3. 获取数据库连接池对象:加载配置文件,然后通过工厂来获取 DruidDataSourceFactory
    4. 获取连接:getConnection
  • 定义工具类

    1. 定义一个类 JDBCUtils
    2. 提供静态代码块加载配置文件,初始化连接池对象
    3. 提供方法:
      1. 获取连接方法:通过数据库连接池获取连接
      2. 释放资源
      3. 获取连接池对象的方法
  • 代码实现示例

        public class JDBCUtils {
    
        private static DataSource ds;
    
        //数据库连接池的初始化
        static {
            try {
                Properties prop = new Properties();
                prop.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
                ds = DruidDataSourceFactory.createDataSource(prop);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        //获取连接的方法
        public static Connection getConnection() throws SQLException {
            return ds.getConnection();
        }
    
        //释放资源的方法
        public static void close(Connection conn, Statement st, ResultSet rs) {
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (st != null) {
                try {
                    st.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }
    
        //释放资源的方法
        public static void close(Connection conn, Statement st) {
            close(conn, st, null);
        }
    
        //获取连接池对象的方法
        public static DataSource getDataSource() {
            return ds;
        }
    
    }

Spring JDBC

  • Spring框架对JDBC的简单封装。提供了一个JDBCTemplate对象简化JDBC的开发。

  • 步骤:

    1. 导入jar包。
    2. 创建JDBCTemplate对象。依赖于数据源DataSource。
    3. 调用DBCTemplate来完成增删改查的操作。
      • update():执行DML语句。
      • queryForMap():查询结果将结果集封装为Map集合,将一条记录封装为Map集合。
        • 注意:这个方法查询的结果集长度只能是1。
      • queryForList():查询结果将结果集封装为List集合。
        • 注意:将每一条记录封装为Map集合,再将map集合装载到List集合中。
      • query():查询结果将结果封装为JavaBean对象。
        • 参数:RowMapper
          • 一般我们使用BeanPropertyRowMapper实现类。可以完成数据到JavaBean的自动封装
          • new BeanPropertyRowMapper<类型>(类型.class)
      • queryForObject():查询结果将结果封装为对象。
        • 一般用于聚合函数的查询。
        • queryForObject(sql语句, 返回值类型.class);

HTML

HTML

  • 概念:是最基础的网页开发语言
    • Hyper Text Markup Language 超文本标记语言
      • 超文本:超文本是用超链接的方法,将各种不同空间的文字信息组织在一起的网状文本。
      • 标记语言:由标签构成的语言。

几类标签的学习

1.文件标签:构成html最基本的标签

  • htlm:html文档的根标签。
  • head:头标签。用于指定html文档的一些属性。引入外部的资源。
  • title:标题标签。
  • body:体标签。
  • < !DOCTYPE html > :html5中定义该文档是html文档。

2.文本标签:和文本有关的标签

  • 注释:< !–注释内容–>

  • < h1> to < h6>:标题标签

  • < p>:段落标签

  • < br>:换行

  • < hr>:显示一条水平线

  • < b>:粗体

  • < i>:斜体

  • < center>:文本居中

  • < font>:字体标签(HTML5不再支持)

    • color:颜色
    • size:大小
    • face:字体
  • 属性定义:(HTML5中也推荐不再支持)

    • color:
      1. 英文单词定义
      2. rgb(值1,值2,值3)
      3. #值1值2值3,值为十六进制
    • width:
      1. 数值:width=’20’,数值单位默认是px(像素)
      2. %数值:表示相对于父元素的占比

3.图片标签

  • < img>:展示一张图片
    • 以./开头的路径表示以当前目录开始
    • 以../开头的路径表示退回上一层路径

4.列表标签

  • 有序列表
    • < ol>
    • < li>
  • 无序列表
    • < ul>
    • < li>

5.链接标签

  • < a>:定义一个超链接
    • 属性:
      • href:指定访问资源的URL
      • target:
        • _blank 在新窗口中打开被链接文档。
        • _self 默认。在相同的框架中打开被链接文档。
        • _parent 在父框架集中打开被链接文档。
        • _top 在整个窗口中打开被链接文档。

6.表格标签

  • < table>:定义表格
    • width:宽度
    • border:边框
    • cellpadding:定义内容和单元格的距离。
    • cellspacing:定义单元格之间的距离,如果为0,则边框线合为一体只有一条。
    • bgcolor:背景色
  • < td>:定义单元格
    • colspan:合并列
    • rowspan:合并行
  • < tr>:定义行
  • < th>:定义表头单元格
  • < caption>:表格标题
  • < thead>:表示表格的头部分
  • < tbody>:表示表格的体部分
  • < tfoot>:表示表格的脚部分

7.div和span标签

  • < span>:文本信息在一行展示,行内标签,内联标签。
  • < div>:每一个div占满一整行。块级标签。

8.语义化标签

html5中为了提高程序的可读性,提供了一些标签。

  • < header>
  • < footer>
  • ……

9.表单标签

  • 表单:用于采集用户输入的数据的。用于和服务器进行交互。

  • < form>:表单标签

    • 属性:

      • action:指定提交数据的URL
      • method:指定提交方式
        • 分类:一共七种,常用的有两种
          • get:请求参数会在地址栏中显示。请求参数的长度有限制。不太安全。
          • post:请求参数不会在地址栏中显示。会封装在请求体中。请求参数长度没有限制。较为安全。
    • 表单项中的数据想要被提交,必须指定其name属性

  • 表单项标签

    • < input>:可以通过type属性值,改变元素展示的样子

      • type属性:

        • text;文本输入框(默认值)
          • placeholder:指定输入框的提示信息,当有输入时,清空提示信息。
        • password:密码输入框
        • radio:单选框
          • 注意:
            1. 让多个单选框实现单选的效果,则多个单选框的name值必须一样。
            2. 一般会给每一个单选框提供value值,指定其被选中后提交的值。
            3. checked属性可以指定默认选中的值。
        • checkbox:复选框
          • 注意:
            1. 一般会给每一个单选框提供value值,指定其被选中后提交的值。
            2. checked属性可以指定默认选中的值。
        • file:文件选择框
        • hidden:隐藏域,用于提交一些信息
        • submit:提交按钮
        • button:普通按钮
        • image:图片提交按钮,通过src指定图片路径
      • < label>:指定输入项的文字描述信息

        • label的for属性,一般会和input的id属性对应,点击label区域,会让input输入框获得焦点。
    • < select>:下拉列表

      • 子元素:< option>:指定列表项
    • textarea:文本域

      • cows:指定列数
      • rows:指定行数

JDBC

JDBC

  • 概念: Java DataBase Connectivity Java 数据库连接,Java语言操作数据库。

  • JDBC本质: 其实是官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口。各个数据库厂商去实现这套接口,提供数据库驱动jar包。我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。

1.快速入门

  • 步骤:
    1. 导入驱动jar包
      1. 复制mysql-connector-java-8.0.20.jar到项目中自己创建的文件夹下,用于存放各种所需要用到的jar包的文件夹。
      2. 右键 –> Add As Library
    2. 注册驱动
    3. 获取数据库连接对象 Connection
      • 注意:新版本的jdbc需要在url后边加上?serverTimezone=GMT,否则会报错,因为数据库和系统时区差异。
    4. 定义sql
    5. 获取执行sql语句执行对象 Statement
    6. 执行sql,接收返回结果
    7. 处理结果
    8. 释放资源

2.详解各个对象

1.DriverManager:驱动管理对象

  • 功能

    1. 注册驱动:告诉程序该使用哪一个数据库驱动jar包

      • static void registerDriver​(Driver driver) 使用 DriverManager注册给定的驱动程序。

      • 写代码使用:Class.forName("com.mysql.cj.jdbc.Driver");

      • 通过查看源码发现,com.mysql.cj.jdbc.Driver类中包含一个静态代码块,其中静态代码块包含的内容中就是static void registerDriver​(Driver driver)

      • 注意:mysql5之后的驱动jar包可以省略注册驱动的步骤。

    2. 获取数据库连接

      • 方法:static Connection getConnection​(String url, String user, String password)
      • 参数:
        • url:指定连接的路径
          • 语法:jdbc:mysql://ip地址(域名):端口号/数据库名称?serverTimezone=GMT
          • 如果连接的是本机的一个mysql服务器,并且mysql服务的端口默认是3306,则这个url的ip和端口可以不写。
        • user:用户名
        • password:密码

2.Connection:数据库连接对象

  • 功能

    1. 获取执行sql的对象

      • Statement createStatement​()
      • PreparedStatement prepareStatement​(String sql)
    2. 管理事务

      • 开启事务 void setAutoCommit​(boolean autoCommit) 参数为false,则为开启事务。
      • 提交事务 void commit​()
      • 回滚事务 void rollback​()

3.Statement:执行sql的对象

  • 功能:执行sql
    1. boolean execute​(String sql) 可以执行任意sql语句。
    2. int executeUpdate​(String sql) 可以执行DML(insert,update,delete)与DDL(create,alter,drop)语句。
      • 返回值:影响的行数,可以通过这个影响的行数判断DML语句是否执行成功,返回值大于0则执行成功,反之,失败。
    3. ResultSet executeQuery​(String sql) 可以执行DQL(select)语句。

4.ResultSet:结果集对象

  • boolean next():游标向下移动一行。
  • getXxx(参数):获取数据。
    • Xxx:代表数据类型
    • 参数:
      1. int:代表列的编号,从1开始。
      2. String:代表列名称。

5.PreparedStatement:执行sql的对象,功能比Statement更强大

  1. SQL注入问题:在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题。

    1. 输入用户名随便,输入密码:a’ or “a” = ‘a
    2. sql: select * from user where username=’dsadsdcz’ and password=’a’ or ‘a’=’a’;
  2. 解决SQL注入问题:使用PreparedStatement对象来解决。

  3. 预编译的SQL:参数使用?作为占位符。

  4. 步骤

    1. 导入驱动jar包
    2. 注册驱动
    3. 获取数据库连接对象 Connection
    4. 定义sql
      • 注意:sql的参数使用?作为占位符。如select * from user where username=? and password=?;
    5. 获取执行sql语句的对象PreparedStatement。Connection.PreparedStatement(String sql)
    6. 给?赋值
      • 方法:setXxx(参数1,参数2)
        • 参数1:?的位置编号,从1开始。
        • 参数2:?的值。
    7. 执行sql,接收返回结果,不需要传递sql语句
    8. 处理结果
    9. 释放资源
  • 注意:后期都会使用PreparedStatement来完成增删改查的所有操作。因为可以防止SQL注入而且效率更高。

JDBC工具类:JDBCUtils

  • 目的:简化书写
  • 分析:
    1. 注册驱动。
    2. 抽取一个方法获取连接对象。
    3. 抽取一个方法释放资源。
      • 可以不用传递参数,还能保证工具类的通用性,可以使用一个properties配置文件。

代码实现示例:

  1. properties配置文件:

    url= jdbc:mysql://localhost:3306/db2?serverTimezone=GMT
    user=root
    password=000000
    driver=com.mysql.cj.jdbc.Driver
  2. 代码

    public class JDBCUtils {
    
    private static String url = null;
    private static String user = null;
    private static String password = null;
    private static String driver = null;
    
    //静态代码块,只执行一次,用于注册驱动和变量的初始化
    static {
        try {
            Properties prop = new Properties();
            ClassLoader classLoader = JDBCUtils.class.getClassLoader();
            URL res = classLoader.getResource("jdbc.properties");
            String path = res.getPath();
            // 因为我的路径中存在中文,所以需要对其进行编码的处理
            path = URLDecoder.decode(path, StandardCharsets.UTF_8);
            System.out.println(path);
            prop.load(new FileReader(path));
            url = prop.getProperty("url");
            user = prop.getProperty("user");
            password = prop.getProperty("password");
            driver = prop.getProperty("driver");
            Class.forName(driver);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    
    /**
    * 获取连接的方法
    * @return Connection对象
    * @throws SQLException
    */
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url, user, password);
    }
    
    /**
    * 资源释放
    * @param st
    * @param conn
    */
    public static void close(Statement st, Connection conn) {
        if (st != null) {
            try {
                st.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
    
    /**
    * 资源释放
    * @param st
    * @param conn
    * @param rs
    */
    public static void close(Statement st, Connection conn, ResultSet rs) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (st != null) {
            try {
                st.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    } 
    }

JDBC控制事务

  1. 使用Connection对象来管理事务
    • 开启事务 void setAutoCommit​(boolean autoCommit) 参数为false,则为开启事务。在sql执行前开启。
    • 提交事务 void commit​()当所有sql执行完提交事务。
    • 回滚事务 void rollback​()在catch中回滚事务。

SQL小知识杂谈

SQL的一些小知识


多表关系的实现

  1. 一对多(多对一)

    • 实现方式:在多的一方建立外键,指向一的一方的主键。
  2. 多对多

    • 实现方式:需要借助第三张中间表,中间表至少包含两个字段,这两个字段作为第三张表的外键,分别指向两张表的主键。

    • 联合主键:中间表的主键可以是指向另两张表主键的两个外键的联合。例:PRIMARY KEY(rid,uid);*

  3. 一对一

    • 实现方式:可以在任意一方添加唯一外键指向另一方的主键(一对一关系不常用,如果是一对一,为何不把两张表拼在一起呢)。

数据库设计范式

范式就是设计数据库时需要遵循的一些规范。

范式有六种范式:第一范式(1NF),第二范式(2NF),第三范式(3NF),巴斯-科德范式(BCNF),第四范式(4NF),第五范式(5NF,又称完美范式)。

各种范式呈递次规范,越高的范式,数据库冗余越小。一般设计数据库时满足前三范式就可以了。

第一范式(1NF)

每一列都是不可分割的原子数据项。

第二范式(2NF)

在1NF的基础上,非码属性必须完全依赖于候选码(在1NF基础上消除非主属性对主码的部分函数依赖)。

就是消除部分依赖。

  • 几个概念

    1. 函数依赖:A –>B,如果通过A属性(属性组)的值,可以确定唯一B属性的值,则B依赖于A。

      • 例:学号 –>姓名 (学号,课程名称) –>分数
    2. 完全函数依赖:A –>B,如果A是一个属性组,则B属性值的确定需要依赖于A属性组中所有的属性值。

      • 例:(学号,课程名称) –>分数
    3. 部分函数依赖:A –>B,如果A是一个属性组,则B属性值的确定需要依赖于A属性组中某一些属性值即可。

      • 例:(学号,课程名称) –>姓名
    4. 传递函数依赖:A –>B, B –>C,如果通过A属性(属性组)的值,可以确定唯一B属性的值,再通过B属性的值可以确定唯一C属性的值,则称C传递函数依赖于A。

      • 例:学号 –>姓名,姓名 –>系主任
    5. 码:如果在一张表中,一个属性或属性组,被其他所有属性完全依赖,则称这个属性(属性组)为该表的码。

      • 例:(学号,课程名称)
      • 主属性:码属性组中的所有属性
      • 非主属性:去除码属性组中的属性

第三范式(3NF)

在2NF基础上,任何非主属性不依赖于其它非主属性(在2NF基础上消除传递依赖)。

就是消除传递依赖。


多表查询

1.内连接查询

  1. 隐式内连接:使用WHERE条件消除无用数据

    • 例:SELECT * FROM emp,dept WHERE emp.id=dept.id;
  2. 显式内连接:

    • 语法
      • SELECT 字段列表 FROM 表名1 [INNER] JOIN 表名2 ON 条件列表;
  3. 内连接查询:

    1. 从哪些表中查数据。
    2. 条件是什么。
    3. 查询哪些字段。

2.外连接查询

  1. 左外连接:

    • 语法:SELECT 字段名 FROM 表名1 LEFT [OUTER] JOIN 表名2 ON 条件列表;

    • 查询的是左表(表名1的表)所有数据以及其符合查询条件的交集部分。

  2. 右外连接:

    • 语法:SELECT 字段名 FROM 表名1 RIGHT [OUTER] JOIN 表名2 ON 条件列表;

    • 查询的是右表(表名2的表)所有数据以及其符合查询条件的交集部分。

3.子查询

就是查询中嵌套查询,被嵌套的查询称为子查询。
例:

1. SELECT MAX(salary) FROM emp;
2. SELECT * FROM emp WHERE salary = 9000;

可以替换为子查询
SELECT * FROM emp WHERE salary = (SELECT MAX(salary) FROM emp);
  • 子查询的不同情况

    1. 子查询结果是单行单列:

      • 子查询可以作为条件,使用运算符去判断。
      • SELECT * FROM emp WHERE salary < (SELECT AVG(salary) FROM emp);
    2. 子查询结果是多行单列:

      • 子查询可以作为条件,使用运算符IN去判断。
      • SELECT * FROM emp WHERE dept_id IN (SELECT id FROM dept WHERE NAME = '财务部' OR NAME = '市场部');
    3. 子查询结果是多行多列:

      • 子查询可以作为一张虚拟表参与查询。
      • SELECT * FROM dept t1, (SELECT * FROM emp WHERE join_date > '2011-11-11') t2 WHERE t1.id = t2.dept_id;

事务

  1. 基本介绍

    1. 概念:

      • 如果一个包含多个步骤的业务操作,被事务处理,那么这些操作要么同时成功,要么同时失败。
    2. 操作:

      1. 开启事务:START TRANSACTION;
      2. 回滚:ROLLBACK;
      3. 提交:COMMIT;
    3. MySQL数据库中事务默认自动提交

      • 事务提交的两种方式:

        • 自动提交:
          • MySQL就是自动提交的。
          • 一条DML语句会自动提交一次事务。
        • 手动提交:
          • Oracle默认是手动提交的。
          • 需要先开启事务,再提交。
      • 修改事务的默认提交方式:

        • 查看事务的默认提交方式:SELECT @@AUTOCOMMIT;
        • 修改默认提交方式:SET @@AUTOCOMMIT = 0;
  2. 事务的四大特征

    1. 原子性:是不可分割的最小操作单位,要么同时成功,要么同时失败。
    2. 持久性:当事务提交或者回滚后,数据库将会持保存数据。
    3. 隔离性:多个事务之间,相互独立。
    4. 一致性:事务操作前后数据总量不变。
  3. 事务的隔离级别

    • 概念:多个事务之间,相互独立的。但是如果多个事务操作同一批数据,则会引发一些问题,设置不同的隔离级别就可以解决这些问题。

    • 存在问题:

      1. 脏读:一个事务读取到另一个事务中没有提交的数据。
      2. 不可重复读(虚读):在同一个事务中两次读取到的数据不一样。
      3. 幻读: 一个事务操作(DML)数据表中所有的记录,另一个事务添加了一条数据,则第一个事务查询不到自己的修改。
    • 隔离级别

      1. read uncommited:读未提交
        • 产生的问题:脏读,不可重复读,幻读。
      2. read commited:读已提交(Oracle)
        • 产生的问题:不可重复读,幻读。
      3. repeatable read:可重复读 (MySQL)
        • 产生的问题:幻读。
      4. serializable:串行化
        • 可以解决所有 的问题。
      • 注意:隔离级别从小到大安全性越来越高,但是效率越来越低。
      • 数据库查询隔离级别:
        • SELECT @@TX_ISOLATION;
      • 数据库设置隔离级别:
        • SET GLOBAL TRANSACTION ISOLATION LEVEL 级别字符串;

常用的SQL语句

常用的SQL语句


DDL

DDL是操作是数据库和表的SQL语句。

1. 操作数据库

  1. 创建

    • 创建数据库

      • CREATE DATABASE 数据库名称;
    • 创建数据库,判断不存在,再创建

      • CREATE DATABASE IF NOT EXISTS 数据库名称;
    • 创建数据库,并指定字符集

      • CREATE DATABASE 数据库名称 character set 字符集名;
    • 创建数据库,判断不存在,再创建,并指定字符集

      • CREATE DATABASE IF NOT EXISTS 数据库名称 character set 字符集名;
  2. 查询

    • 查询所有数据库的名称

      • SHOW DATABASES;
    • 查询某个数据库的字符集,查询某个数据库的查询语句

      • SHOW CREATE DATABASE 数据库名称;
  3. 修改

    • 修改数据库的字符集
      • ALTER DATABASE 数据库名称 character set 字符集名;
  4. 删除

    • 删除数据库

      • DROP DATABASE 数据库名称;
    • 判断数据库存在,再删除

      • DROP DATABASE IF EXISTS 数据库名称;
  5. 使用数据库

    • 查询当前正在使用的数据库名称

      • SELECT DATABASE();
    • 使用数据库

      • USE 数据库名称;

2. 操作表

  1. 创建

    • 创建表

      CREATE TABLE 表名称(
          列名1,数据类型1,
          列名2,数据类型2,
          列名3,数据类型3,
          .......
          列名n,数据类型n
      );
    • 注意最后一列后面不用加逗号

    • SQL中常用的数据类型

      1. int:整数类型
      2. double:小数类型
      3. date:日期,只包含年月日,yyyy-MM-dd
      4. datetime:日期,包含年月日时分秒,yyyy-MM-dd HH:mm:ss
      5. timestamp:时间戳类型,包含年月日时分秒,不赋值时可以默认添加当前系统时间
      6. varchar:字符串
    • 复制表

      • CREATE TABLE 表名 LIKE 被复制的表名;
  2. 查询

    • 查询某个数据库中所有表的名称
      • SHOW TABLES;
    • 查询表结构
      • DESC 表名称;
  3. 修改

    • 修改表名

      • ALTER TABLE 表名称 RENAME TO 新的表名;
    • 修改表的字符集

      • ALTER TABLE 表名称 character set 字符集名;
    • 添加一列

      • ALTER TABLE 表名称 ADD 列名 数据类型;
    • 修改列名和类型

      • ALTER TABLE 表名称 CHANGE 列名 新列名 新数据类型;
      • ALTER TABLE 表名称 MODIFY 列名 新数据类型;
    • 删除列

      • ALTER TABLE 表名称 DROP 列名;
  4. 删除

    • 删除表

      • DROP TABLE 表名称;
    • 判断表存在,再删除

      • DROP TABLE IF EXISTS 表名称;

DML

DML是增删改数据库的表中的数据的SQL语句。

  1. 添加数据

    • INSERT INTO 表名(列名1,列名2,列名3,…..列名n) VALUES(值1,值2,值3,…..值n);

    • 注意:

    1. 列名和值要一一对应。

    2. 如果表名后,不定义列名,则默认给所有列添加值。

      • INSERT INTO 表名VALUES(值1,值2,值3,…..值n);
    3. 除了数字类型,其他类型需要使用引号(单双引号都可以)引起来。

  2. 删除数据

    • DELETE FROM 表名 [WHERE 条件];

    • 注意:如果不加条件,则删除表中所有记录。

    • 如果要删除表中所有记录,不推荐使用DELETE FROM 表名;,可以使用TRUNCATE TABLE 表名;

  3. 修改数据

    • UPDATE 表名 SET 列名1=值1, 列名2=值2,….列名n=值n [WHERE 条件];

    • 注意:如果不加任何条件,则会将表中所有记录修改。


DQL

DQL是查询表中记录的SQL语句。

  • SELECT * FROM 表名;

语法:

SELECT
    字段列表
FROM
    表名列表
WHERE
    条件列表
GROUP BY
    分组字段
HAVING
    分组之后的条件
ORDER BY
    排序
LIMIT
    分页限定

1. 基础查询

  1. 多个字段的查询

    • SELECT 字段名1,字段名2… FROM 表名;
  2. 去除重复

    • SELECT DISTINCT 字段名1,字段名2… FROM 表名;
  3. 计算列

    • 一般可以使用四则运算计算一些列的值。(一般只会进行数值型的计算)
    • IFNULL(表达式1,表达式2):NULL参与的运算,计算结果都为NULL。
      • 表达式1:哪个字段需要判断是否为NULL。
      • 表达式2:如果该字段为NULL后的替换值。
  4. 起别名

    • SELECT 字段名1 AS 别名 FROM 表名;

    • 注意:AS也可以省略,用一个空格代替。

2. 条件查询

  1. WHERE子句后跟条件。

  2. 运算符

    • < > >= <= <> =
    • BETWEEN…AND
    • IN(集合)
    • LIKE:模糊查询
      • 占位符:
        • _:单个任意字符。
        • %:多个任意字符。
    • IS NULL
    • AND 或 &&
    • OR 或 ||
    • NOT 或 !

3. 排序查询

  • 语法

    • ORDER BY 排序字段1 排序方式1,排序字段2 排序方式2….
  • 排序方式

    • ASC:升序,默认的。

    • DESC:降序。

    • 注意:如果有多个排序条件,则当前边的条件值一样时,才会判断第二条件。

4. 聚合函数

将一列数据作为一个整体,进行纵向的计算。

注意:聚合函数的计算会排除NULL值

解决方案:1.选择不包含空的列(主键)进行计算。2.IFNULL函数。

  1. COUNT;计算个数。
    • SELECT COUNT(字段名) FROM 表名;
  2. MAX;计算最大值。
    • SELECT MAX(字段名) FROM 表名;
  3. MIN;计算最小值。
    • SELECT MIN(字段名) FROM 表名;
  4. SUM:计算和。
    • SELECT SUM(字段名) FROM 表名;
  5. AVG;计算平均值。
    • SELECT AVG(字段名) FROM 表名;

5. 分组查询

  • 语法:

    • GROUP BY 分组字段;
    • SELECT 分组字段, 聚合函数1,…. FROM 表名 GROUP BY 分组字段;
  • 注意:1.分组之后查询的字段只能是分组字段或者聚合函数。2.在分组之前可以用WHERE进行条件限定且后面不可以跟聚合函数判断,如果要在分组之后进行条件限定需要用HAVING且后面可以跟聚合函数判断。

    SELECT 分组字段, 聚合函数1,.... FROM 表名 WHERE 条件 GROUP BY 分组字段 HAVING 条件;

6. 分页查询

  • 语法:
    • LIMIT 开始的索引,每页查询的条数;
    • SELECT * FROM 表名 LIMIT 开始的索引, 每页查询的条数;

LIMIT是一个“方言”,只能在MySQL中用。


DCL

1.管理用户

  1. 添加用户:

    • CREATE USER ‘用户名‘@’主机名’ IDENTIFIED BY ‘密码’;
  2. 删除用户:

    • DROP USER ‘用户名‘@’主机名’;
  3. 修改用户密码:

    • UPDATE USER SET PASSWORD = PASSWORD(‘新密码’) WHERE USER = ‘用户名’;

    • SET PASSWORD FOR ‘用户名‘@’主机名’ = PASSWORD(‘新密码’);

    • MySQL中忘记了root用户的密码怎么办?

      1. cmd –> net stop mysql80 停止mysql服务
      2. 使用无验证方式启动mysql服务:mysqld –skip-grant-tables
      3. 打开新的cmd窗口,直接输入mysql命令,敲回车,就可以登陆成功
      4. USE mysql;
      5. UPDATE USER SET PASSWORD = PASSWORD(‘新密码’) WHERE USER = ‘root’;
      6. 关闭两个窗口
      7. 打开任务管理器,手动关闭mysqld.exe的进程
      8. 启动mysql服务
      9. 使用新密码登录
  4. 查询用户:

    1. 切换到mysql数据库。USE mysql;
    2. 查询user表。SELECT * FROM user;
    • 通配符:%表示可以在任意主机使用用户登录数据库。

2.权限管理

  1. 查询权限:

    • SHOW GRANTS FOR ‘用户名‘@’主机名’;
  2. 授予权限

    • GRANT 权限列表 ON 数据库名.表名 TO ‘用户名‘@’主机名’;
    • GRANT ALL ON . TO ‘用户名‘@’主机名’; 给一个用户授予对任意数据库中任意表进行任意操作的权限。
  3. 撤销权限

    • REVOKE 权限列表 ON 数据库名.表名 FROM ‘用户名‘@’主机名’;

约束

对表中的数据进行限定,保证数据的正确性、有效性和完整性。

分类:

  1. 主键约束:primary key
  2. 非空约束:not null
  3. 唯一约束:unique
  4. 外键约束:foreign key

1.非空约束

某一列的值不能为NULL。

  • 创建表时添加非空约束

    CREATE TABLE 表名(
        字段名1 数据类型1,
        字段名2 数据类型2 NOT NULL,
        .....
    );
  • 创建表完后添加非空约束

    ALTER TABLE 表名 MODIFY 字段名 数据类型 NOT NULL;

  • 删除非空约束

    ALTER TABLE 表名 字段名 数据类型;

2.唯一约束

某一列的值不能重复。

  • 创建表时,添加唯一约束

    CREATE TABLE 表名(
        字段名1 数据类型1,
        字段名2 数据类型2 UNIQUE,
        .....
    );
  • 删除唯一约束

    ALTER TABLE 表名 DROP INDEX 字段名;

  • 在表创建完后,添加唯一约束

    ALTER TABLE 表名 MODIFY 字段名 数据类型 UNIQUE;

3.主键约束

某一列的值非空且唯一,一张表只能有一个字段为主键,就是表中记里的唯一标识。

  • 创建表时,添加主键约束

    CREATE TABLE 表名(
        字段名1 数据类型1,
        字段名2 数据类型2 PRIMARY KEY,
        .....
    );
  • 删除主键

    ALTER TABLE 表名 DROP PRIMARY KEY;

  • 创建完表后,添加主键

    ALTER TABLE 表名 MODIFY 字段名 数据类型 PRMARY KEY;

  • 自动增长

    • 如果某一列是数值类型,使用AUTO_INCREMENT可以完成值自动增长,一般可以配合数值类型的主键使用。

    • 注意:自动增长的值为最后一条记录自动增长字段的值加一

    • 创建表时,添加主键,并且完成自动增长

      CREATE TABLE 表名(
          字段名1 数据类型1,
          字段名2 数据类型2 PRIMARY KEY AUTO_INCREMENT,
          .....
      );
    • 删除自动增长

      ALTER TABLE 表名 MODIFY 字段名 数据类型;

    • 添加自动增长

      ALTER TABLE 表名 MODIFY 字段名 数据类型 AUTO_INCREMENT;

4.外键约束

让表与表产生关系,从而保证数据的正确性,外键可以为NULL,但是不能是主表中不存在的值。

  • 创建表时,添加外键

    CREATE TABLE 表名(
        字段名1 数据类型1,
        字段名2 数据类型2,
        .....
        CONSTRAINT 外键名称 FOREIGN KEY (外键列名称) REFERENCES 主表名称(主表列名称)
    );
  • 删除外键

    ALTER TABLE 表名称 DROP FOREIGN KEY 外键名称;

  • 创建表之后,添加外键

    ALTER TABLE 表名称 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键列名称) REFERENCES 主表名称(主表列名称);

  • 级联操作

    可以在外键关联的主表中的列进行操作时,外键中的值自动更新。

    • 级联更新

      • 在添加外键语句后加上ON UPDATE CASCADE

        ALTER TABLE 表名称 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键列名称) REFERENCES 主表名称(主表列名称) ON UPDATE CASCADE;

    • 级联删除

      • 在添加外键语句后加上ON DELETE CASCADE

        ALTER TABLE 表名称 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键列名称) REFERENCES 主表名称(主表列名称) ON DELETE CASCADE;

级联更新与级联删除可以同时存在。


命令行操作数据库备份和还原

  • 备份:MYSQLDUMP -u用户名 -p密码 数据库名称 > 保存的路径;

  • 还原:

    1. 登录数据库
    2. 创建数据库
    3. 使用数据库
    4. 使用文件。SOURCE 文件路径

杂谈:权限修饰符,匿名内部类....

权限修饰符

JAVA中有四种权限修饰符:public,protected,(default),private。

四种权限修饰符权限大小:public > protected > (default) > private

注意:(default)代表什么也不加,例:class person。

权限修饰符在不同范围的权限

public protected (default) private
同一个类 Yes Yes Yes Yes
同一个包 Yes Yes Yes No
不同包子类 Yes Yes No No
不同包非子类 Yes No No No

内部类

如果一个事物内部包含另一个事物,那么这就是一个类包含另一个类。

如:身体和心脏的关系,汽车和发动机的关系

分类:

  1. 成员内部类
  2. 局部内部类(其中包含匿名内部类)

成员内部类

成员内部类的定义格式:

修饰符 class 外部类名称{
    修饰符 class 内部类名称{
        ....
    }
    .....
}

注意:内用外,可以随意访问;外用内,需要借助内部类对象。

如何使用成员内部类?

  1. 间接方式:在外部类的成员方法中,使用内部类,然后main只是调用外部类的方法。

  2. 直接方式:公式

外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称();

注意:内部类访问重名的外部类成员变量:外部类名称.this.成员变量名称


局部内部类(匿名内部类)

如果一个类定义在一个方法内部,那么这就是一个局部内部类。

“局部”:只有当前所属的方法能使用它,出了这个方法外面就不能用了。

定义格式:

修饰符 class 外部类名称 {
    修饰符 返回值类型 外部类方法名称(参数列表) {
        class 局部内部类名称 {
            ....
        }
    }
    .....
}

定义一个类的时候,权限修饰符规则:

  1. 外部类:public/(default)
  2. 成员内部类:public/protected/(default)/private
  3. 局部内部类:什么也不写

局部内部类:如果希望访问所在方法的局部变量,那么这个局部变量必须是有效final的

备注:从java8开始,只要局部变量事实不变,那么final关键字可以省略。

原因:

  1. new出来的对象在堆内存当中。
  2. 局部变量跟着方法走,在栈内存当中。
  3. 方法运行结束之后,立刻出栈,局部变量就会消失。
  4. 但是new出来的对象会在堆当中持续存在,直到垃圾回收消失。

匿名内部类

匿名内部类也是一种局部内部类。

如果接口的实现类(或者是父类的子类)只需使用唯一的一次, 那么这种情况下就可以省略掉这类的定义,而改为使用匿名内部类

匿名内部类的定义格式:

接口名称 对象名 = new 接口名称() {
    //覆盖重写所有抽象方法
}

注意:匿名内部类,在创建对象的时候,只能使用唯一一次。

如果希望多次创建对象,而且类的内容一样的话,那么就必须使用单独定义的实现类了。


以上就是关于内部类的一些简要描述,如需知道更多请自己查询。

JAVA中关于时间的一些类

Calendar日历类

java.util.Calendar:日历类

Calendar类是一个抽象类,里面提供了很多操作日历字段的方法:(YEAR,MONTH,DAY_OF_MONTH,HOUR)。

Calendar类是无法直接创建对象使用的,里面有一个静态方法getInstance(),该方法返回了Calendar类的子类对象

static Calendar getInstance():使用默认时区和语言环境获得一个日历。

Calendar类的常用成员方法:

  1. public int get(int field):返回给定日历字段的值。

  2. public void set(int field, int value):将给定的日历字段设置为给定值。

  3. public abstract void add(int field, int amount):根据日历的规则,为给定的日历字段添加或减去指定的时间量。

  4. public Date getTime():返回一个表示此Calendar时间值(从历元到现在的毫秒偏移量)的Date对象。

成员方法的参数:

int field:日历类的字段,可以使用Calendar类的静态成员变量获取。
public static final int YEAR = 1;           年
public static final int MONTH = 2;          月
public static final int DATE = 5;           月中的某一天
public static final int DAY_OF_MONTH = 5;   月中的某一天
public static final int HOUR = 10;          时
public static final int MINUTE = 12;        分
public static final int SECOND = 13;        秒

Date日期类

java.util.Date:表示日期和时间的类

类Date表示特定的瞬间,精确到毫秒。

毫秒:千分之一秒 1000毫秒等于一秒。

特定的瞬间:一个时间点,一刹那时间。

毫秒值的作用:可以对时间和日期进行计算。

2088-01-05到20-99-03-05到底有多少天?
可以日期转换为毫秒进行计算,计算完毕,再把毫秒转换为日期。

把日期转换为毫秒:
当前的日期:2088-01-01

时间原点(0毫秒):1970年1月1日 00:00:00(英国格林威治)。

就是计算当前日期到时间原点之间一共经历了多少毫秒。

注意:中国是东八区,所以会把时间增加八个小时,即从早上8点开始。

把毫秒转换为日期:
1 天 = 24 X 60 X 60 = 86400 秒 = 86400 X 1000 = 86400000毫秒。

Date类的构造方法

Date();Date类的无参构造方法,获取当前系统的日期和时间。

Date(long time);Date类的有参构造方法,传递毫秒值(long类型),把毫秒值转换为日期。

Date类的常用成员方法

long getTime():把日期转换为毫秒值,返回时间原点到现在系统时间之间的毫秒值(相当于System.currentTimeMillis();)。


DateFormat日期/时间格式化子类的抽象类

java.text.DateFormat是日期/时间格式化子类的抽象类

作用格式化(日期 -> 文本)、解析(文本-> 日期)。

成员方法:

String format(Date date):按照指定的模式,把Date日期,格式化为符合模式的字符串。
Date parse(String source):把符合模式的字符串,解析为一个Date日期。

DateFormat类是一个抽象类,无法直接创建对象使用,可以使用DateFormat类的子类。

java.text.SimpleDateFormat extends DateFormat

构造方法:

SimpleDateFormat(String pattern):用给定的模式和默认语言环境的日期格式符号构造 SimpleDateFormat。

参数:String pattern:传递指定的模式。

模式:区分大小写。

y  年
M  月
d  日
H  时
m  分
s  秒

写对应的模式,会把模式替换为对应的日期和时间。

“yyyy-MM-dd HH-mm-ss”

注意:模式中的字母不能更改,但是连接模式的符号可以改变。

“yyyy年MM月dd日 HH时mm分ss秒”


以上是三个关于时间和日期的类,如需了解更多请自己查询有关内容。

JAVA当中的final关键字

关于final关键字

final关键字代表最终,不可改变的。

final关键字有常见的四种用法:

  • 可以用来修饰一个类
  • 可以用来修饰一个方法
  • 可以用来修饰一个局部变量
  • 可以用来修饰一个成员变量

用final修饰一个类

当final关键字用来修饰一个类的时候。

格式:

public final class 类名称 {
        //.....
}

含义:当前这个类不能有任何的子类。(太监类)

注意: 一个类如果是final的,那么其中所有的成员方法都无法进行覆盖重写(因为没儿子),但是可以对父类继承的方法覆盖重写。


用final修饰一个方法

当final关键字来修饰一个方法的时候,这个方法就是最终方法,也就是不能被覆盖重写

格式:

修饰符 final 返回值类型 方法名称(参数列表){
            方法体....
}

注意事项: 对于类、方法来说,abstract关键字与final关键字不能同时使用,因为矛盾


用final修饰一个局部变量

用final修饰局部变量可以不对其进行赋值,那么这个局部变量将会是初始值不能再改变,当然也可以对其赋值,赋值后也不能再改变。

用final修饰一个成员变量

对于成员变量来说,如果使用final关键字修饰,那么这个变量也照样是不可变。但是用final修饰的成员变量一定要对其手动赋值,不会再给默认值了。赋值方法有两种,妖媚直接赋值,要么通过构造方法赋值。


此为final关键字的一些粗略简介,更多详细信息请自己查询相关内容。

JAVA中的System类与StringBuilder类

System类

java.lang.System类中提供了大量的静态方法,可以获取与系统相关的信息或系统级操作。

在System类的API文档中,常用的方法有:

public static long currentTimeMillis(); 返回以毫秒为单位的当前时间。

public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);将数组中指定数据拷贝到另一个数组中。

public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)方法
参数:
    src - 源数组。
    srcPos - 源数组中的起始位置。
    dest - 目标数组。
    destPos - 目标数据中的起始位置。
    length - 要复制的数组元素的数量。

StringBuilder类

java.lang.StringBuilder类:字符串缓冲区,可以提高字符串的效率。

构造方法:
StringBuilder();构造一个不带任何字符的字符串生成器,其初始容量为 16 个字符。

StringBuilder(String str);构造一个字符串生成器,并初始化为指定的字符串内容。

常用的成员方法:
public StringBuilder append(...);添加任意类型数据的字符串形式,并返回当前对象自身。

public String toString();将当前的StringBuilder对象转换为String对象。

StingBuilder与String的区别

StringBuilder对象中的内容可以改变,而String不行。


以上是关于这两个类的简要描述,如需知道更多请自己查询。

一些自定义类中的方法重写:toString.....

Object类中为我们提供了一些方法,当我们创建自定义类的对象后,想要使用这些方法,可能无法实现我们想要的需求,因此需要我们对Object类的一些方法进行重写。

toString方法

如果不重写此方法,直接打印输出时,toString是将其中的地址值转换为字符串,也就是打印出来的是对象的地址值,因此需要重写,才能将其中的内容转换为字符串,才能把对象中的内容打印出来。

equals方法

Object类的equals方法,默认比较的是两个对象的地址值,没有意义,所以要重写equals方法,比较两个对象的属性

问题:

  • 隐含着一个多态

多态的弊端:无法使用子类的特有内容(属性和方法)

Object obj = p2 = new Person(“古力娜扎”,19);

  • 解决:可以使用向下转型,把obj类型转换为Person。

这些方法都可以用IDEA的自动代码生成,不用手写

请我喝杯咖啡吧~

支付宝
微信