mysql

2020/08/15 database 共 5471 字,约 16 分钟

回顾 mysql 的一些知识点,以及记录之后遇见有趣的代码。

1、 安装

2、 建表以及crud的建议

  • 建表时一定要加上字符设置charset=utf8,因为默认 mysql 的字符集 latin1 不支持中文编码。
  • mysql 默认的数据库引擎为 innodb(5.5以后成为默认的),相比于之前的 MyISAM 二者的区别为:
 MYISAMINNODB
事物支持不支持支持
数据行锁定不支持,只支持表锁定支持
外键约束不支持支持
全文索引支持不支持
表空间大小较小较大,约两倍

​ MYISAM:节约空间,速度较快。 ​ INNODB:安全性高,事物的处理,多表多用户操作。

  • MYSQL 所有的数据库文件都存在data目录,一个文件夹就对应一个数据库
  • 建表时不建议使用物理外键,也就是在表上建外键:因为每次delete/update表时都必须考虑外键约束,表越多外键约束越多开发难度越大。最佳方案为:
    • 数据库就是单纯的表,只用来存数据,只有行(数据)和列(字段)
    • 外键通过应用层(程序代码)实现。
  • 清空表时不建议使用delete from 表名 ,而是用 truncate 表名。好处在于:
    • TRUNCATE 重新设置自增列,计数器会归 0(而 delete 以后并且数据库引擎为 innodb,需要重启数据库计数器才会归 0,这是因为 innodb 会将计数器存在内存中,断点即失,而 MyISAM 是存在文件中)
    • TRUNCATE 不会影响事物

3、 索引

强烈推荐:MySQL索引背后的数据结构及算法原理

4、 备份

#导出;
#mysqldump -h 主机 -u 用户名 -p 密码 数据库 [表1] [表2]... > 物理磁盘位置/文件名
mysqldump -hlocalhost -uroot -p***** school student > D:/b.sql

#导入:
#登录情况下,切换到指定数据库
source D:/b.sql

#无登录情况下
mysql -uroot -p**** 库名 < 备份文件

5、 JDBC

5.1 Demo

准备工作:

  • 环境为:IDEA 2020 + jdk 8.0 + mysql 8.0 + mysql-connector-java-8.0.21.jar
  • 将 mysql 驱动导入 idea 中
  • 将mysql 驱动所在的目录设为 Liberary
public class Test01 {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
    	//1. 加载驱动
        Class.forName("com.mysql.cj.jdbc.Driver");  
        String url = "jdbc:mysql://127.0.0.1:3306/school?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=Asia/Shanghai";
        String username = "root";
        String pas = "redhat";
        
        //2. 连接数据库
        Connection con = DriverManager.getConnection(url,username,pas);
        String sql = "select * from student";
        
        //3. 获得执行的sql对象
        Statement statement =  con.createStatement();
        
        //4. 执行sql 获得结果集
        ResultSet rs =  statement.executeQuery(sql);

        while(rs.next()){
            int id = rs.getInt(1);
            String name = rs.getString(2);
            int age = rs.getInt(3);
            System.out.println(id+" "+name+" "+age);
        }

		//5. 关闭连接
        statement.close();
        con.close();

    }
}

5.2 JDBC 工具类

工具类:

//JDBC工具类
public class Utils {
    static String driver = null;
    static String url= null;
    static String user= null;
    static String pwd= null;
    static{
        InputStream in = Utils.class.getClassLoader().getResourceAsStream("com/lrr/jdbc/db.properties");
        Properties properties = new Properties();
        try {
            properties.load(in);
            driver = properties.getProperty("driver");
            url = properties.getProperty("url");
            user = properties.getProperty("user");
            pwd = properties.getProperty("pwd");

            //驱动只用加载一次:
            Class.forName(driver);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //得到连接
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url,user,pwd);
    }
    //关闭连接
    public static void close(ResultSet rs, Statement statement,Connection con){
        if(rs != null){
            try {
                rs.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if(statement != null){
            try {
                rs.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if(con != null){
            try {
                rs.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}

使用:

public class Test02 {
    public static void main(String[] args) throws SQLException {
        Connection connection = Utils.getConnection();
        Statement statement = connection.createStatement();
        String sql = "select * from student";
        ResultSet rs = statement.executeQuery(sql);
        while(rs.next()){
            System.out.println(rs.getInt("id")+" "+rs.getString("name"));
        }
        Utils.close(rs,statement,connection);
    }
}

5.3 PreparedStatement

PreparedStatement 可以防止 sql 注入。防止的原理是把传递进来的参数当作字符,即使参数存在转义字符,比如说 ‘ ,也会当成字符串。 相当于外面又包了一层。

Demo:

public class Test03 {
    public static void main(String[] args) throws SQLException {
        Connection con = Utils.getConnection();
        String sql = "select * from student where id =?";   //占位符
        PreparedStatement ps = con.prepareStatement(sql);
        ps.setInt(1,1);                 //将具体的值替换占位符
        ResultSet rs = ps.executeQuery();
        while(rs.next()){
            System.out.println(rs.getInt("id")+" "+rs.getString("name"));
        }
        Utils.close(rs,ps,con);
    }
}

使用 Statement 时,sql 注入语句为: 
	String id = "2323 or 1 = 1";
	String sql = "select * from student where id ="+ id;
拼接后为:select * from student where id = 2323 or 1 = 1。而这句话会将表中所有数据都得到

而使用 PreparedStatement 时,sql 注入语句为: 
	String sql = "select * from student where name =?";   //占位符
    ps.setString(1,"2323 or 1 = 1");     
拼接后为:select * from student where name = "2323 or 1 = 1"。也就是说在 2323 or 1 = 1 外面又加上"" ,从而将整个输入当作字符串。

6、 数据库连接池

编写连接池,需要实现一个接口:DataSource

有三个流行的 具体实现方案:DBCP,C3P0 ,Druid。三者之间的比较

使用了这些数据库连接池之后,在项目开发中就不需要编写连接数据库的代码了。

需要的 jar 包: DBCP :commons-dbcp 、 commons-pool C3P0 : c3p0 、 mchange-commons-java

6.1、 DBCP

  • 下载 commons-dbcp 、 commons-pool 还有可能需要 commons-logging-1.2 、tomcat-juli-10.0.0-M7
  • 新建 *.properties 文件 (dbcp.properties),内容为: ```properties driverClassName=com.mysql.cj.jdbc.Driver url=jdbc:mysql://localhost:3306/school username=root password=redhat

#初始化时连接池中connection数量 initialSize=10

#最大连接数量 maxActive=50

#最大的空闲连接数量 maxIdle=20

#最小的空闲链接数量 minIdle=5

#最大的等待时间,单位是毫秒 maxWait=60000 #建立连接时的附加参数,如果指定的编码不一致数据库中会出现乱码 connectionProperties=useUnicode=true;characterEncoding=utf8;serverTimezone=Asia/Shanghai

#是否开启自动提交,跟事务的控制有关 defaultAutoCommit=true

#指定由连接池所创建的连接的事务隔离级别(TransactionIsolation)。 defaultTransactionIsolation=REPEATABLE_READ


+ Utils_dbcp:

```java
public class Utils_dbcp {
    static BasicDataSource basicDataSource = null;
    static InputStream in = null;
    static Properties properties = null;
    static{
        in = Utils_dbcp.class.getClassLoader().getResourceAsStream("com/lrr/jdbc/dbcp.properties");
        properties = new Properties();
        try {
            properties.load(in);
            try {
                basicDataSource = BasicDataSourceFactory.createDataSource(properties);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //得到连接
    public static Connection getConnection() throws SQLException {
        return basicDataSource.getConnection();
    }
    //关闭连接
    public static void close(ResultSet rs, Statement statement, Connection con){
        if(rs != null){
            try {
                rs.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if(statement != null){
            try {
                rs.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if(con != null){
            try {
                rs.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}

文档信息

Search

    Table of Contents