20220705

软件开发中,关于数据库的设计

  • 分析需求:分析业务和需要处理的数据库的需求;
  • 概要设计:设计关系图E-R图

前端软件:Element ui  、Semantic ui、layui、ant design pro

三大范式

 1.JDBC 

Java操作数据库的规范,简化开发人员对数据库的统一操作。

JDBC连接数据库:

导入jar包:mysql-connector-java-8.0.13.jar

(1)加载驱动

Class.forName("com.mysql.cj.jdbc.Driver");

(2)用户信息和url

//userUnicode=true 支持中文编码 characterEncoding=utf8 设定字符为utf-8  useSSL=true 使用安全连接
String url = "jdbc:mysql://localhost:3306/jdbcstudy?" +
        "useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2B8";
String username = "root";
String password = "123456";

(3)连接数据库,返回数据库对象(DriverManager)

//connection 代表数据库
Connection connection = DriverManager.getConnection(url, username, password);

(4)执行SQL对象(Statement)

Statement statement = connection.createStatement();

(5)执行SQL,存在结果集,查看返回结果(resultSet)

String sql = "SELECT * FROM users";
ResultSet resultSet = statement.executeQuery(sql); //返回结果集,链表的形式
//resultSet 结果集中封装了我们全部查询出来的结果
while(resultSet.next()){  //字段名与数据库一致
    System.out.println("id="+resultSet.getObject("id"));
    System.out.println("name="+resultSet.getObject("name"));
    System.out.println("pwd="+resultSet.getObject("password"));
    System.out.println("email="+resultSet.getObject("email"));
    System.out.println("birthday="+resultSet.getObject("birthday"));
    System.out.println("--------------------------------------------------");
}

(6)关闭连接

resultSet.close();
statement.close();
connection.close();

Statement执行SQL的对象

statement.executeQuery();//查询操作返回ResultSet
statement.executeUpdate();//更新、插入、删除,返回受影响的行数
statement.execute();//执行任意SQL

ResultSet返回结果集,封装了全部的查询结果

resultSet.getObject();//在不知道列数据类型的情况下使用
resultSet.getInt();
resultSet.getString();
resultSet.beforeFirst();//移动到最前面
resultSet.afterLast();//移动到最后面
resultSet.previous();//移动到前一行
resultSet.absolute(row);//移动到指定行

2. Statement对象

Statement对象用于向数据库发送SQL语句,完成对数据库的增、删、改、查。

查询:statement.executeQuery();
更新、插入、删除:statement.executeUpdate();

(1)增、删、改

String sql = "insert into user(...) values(...)";
String sql = "delete from user where id =...";
String sql = "update user set name = '' where name = ''";
int num = statement.executeUpdate(sql);

 (2)查询

String sql = "select * from user where id =... ";
ResultSet resultSet = statement.executeQuery(sql);

 3. 封装工具类,实现增删改查功能

(1)在src目录下添加文件,将连接数据库的信息放在文件中

//db.properties(src目录下)
driver = com.mysql.cj.jdbc.Driver
url = jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2B8
username = root
password = 123456

(2)封装连接数据库、释放资源操作

//JdbcUtils.java
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

public class JdbcUtils {
    private static String driver = null;
    private static String url = null;
    private static String username = null;
    private static String password = null;
    static {
        try{
            InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
            Properties properties = new Properties();
            properties.load(in);

            driver = properties.getProperty("driver");
            url = properties.getProperty("url");
            username = properties.getProperty("username");
            password = properties.getProperty("password");

            //1.加载驱动
            Class.forName(driver);
        }catch (Exception e) {
            e.printStackTrace();
        }
    }
    //获取连接
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url,username,password);
    }
    //释放连接资源
    public static void release(Connection conn, Statement st, ResultSet rs){
        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(st!=null){
            try {
                st.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

(3)获取数据库连接,实现增删改操作

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

public class TestInsert {
    public static void main(String[] args) {
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;
        try {
            conn = JdbcUtils.getConnection(); //获取数据库连接
            st = conn.createStatement(); //获得sql的执行对象
            String sql = "INSERT into users (id,`name`,`password`,`email`,`birthday`) VALUES(4,'zhaoliu','123456','zhaoliiu@sina.com','2000-01-01')";
            //String sql = "DELETE FROM users WHERE id = 4";
            //String sql ="UPDATE users SET `name`="张三" WHERE id = 1";
            int i = st.executeUpdate(sql);  //增删改的方法
            if(i>0){
                System.out.println("插入成功!");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.release(conn,st,rs);
        }
    }
}

(4)获取数据库连接,实现查询操作

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

public class TestQuery {
    public static void main(String[] args) {
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;
        try {
            conn = JdbcUtils.getConnection();
            st = conn.createStatement();
            String sql = "SELECT * FROM users WHERE id = 2";
            rs = st.executeQuery(sql);
            while(rs.next()){
                System.out.println("id = " + rs.getInt("id"));
                System.out.println("name = " + rs.getString("name"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.release(conn,st,rs);
        }
    }
}

4. SQL注入问题

sql存在漏洞,会被攻击,导致数据泄露(SQL会被拼接)

select * from users where `name` ="'  ' or '1=1'" and `password` = "'  ' or '1=1'" ;

5. PreparedStatement对象

 PreparedStatement可以防止SQL注入,效率更高!把传递过来的参数当作字符,比如说'会被直接转义。

使用preparedStatement执行插入操作

import java.util.Date;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class PrepareInsert {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement pst = null;
        ResultSet rs = null;

        try {
            conn =JdbcUtils.getConnection();
            String sql = "insert into users (id,`name`,`password`,`email`,`birthday`) VALUES(?,?,?,?,?)";
            pst = conn.prepareStatement(sql); //预编写sql,先写sql,然后不执行
            //手动给参数赋值
            pst.setInt(1,4);
            pst.setString(2,"赵六");
            pst.setString(3,"123456");
            pst.setString(4,"123321@qq.com");
            pst.setDate(5,new java.sql.Date(new Date().getTime()));
            //执行
            int i = pst.executeUpdate();
            if(i>0){
                System.out.println("插入成功!");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.release(conn,pst,rs);
        }
    }
}

使用PreparedStatement执行删除操作

try {
    conn =JdbcUtils.getConnection();
    String sql = "delete  from users where id =?";
    pst = conn.prepareStatement(sql); //预编写sql,先写sql,然后不执行
    //手动给参数赋值
    pst.setInt(1,4);
    //执行
    int i = pst.executeUpdate();
    if(i>0){
        System.out.println("删除成功!");
    }
} catch (SQLException e) {
    e.printStackTrace();
}finally {
    JdbcUtils.release(conn,pst,rs);
}

使用PreparedStatement执行修改操作

try {
     conn =JdbcUtils.getConnection();
     String sql = "UPDATE users SET `name`=? WHERE id = ?";
     pst = conn.prepareStatement(sql); //预编写sql,先写sql,然后不执行
     //手动给参数赋值
     pst.setString(1,"lisi");
     pst.setInt(2,2);
     //执行
     int i = pst.executeUpdate();
     if(i>0){
         System.out.println("修改成功!");
     }
} catch (SQLException e) {
      e.printStackTrace();
}finally {
      JdbcUtils.release(conn,pst,rs);
}

 使用PreparedStatement执行查询操作

try {
    conn =JdbcUtils.getConnection();
    String sql = "SELECT * FROM users WHERE id = ?";
    pst = conn.prepareStatement(sql); //预编写sql,先写sql,然后不执行
    //手动给参数赋值
    pst.setInt(1,1);
    //执行
    rs = pst.executeQuery();
    if(rs.next()){
        System.out.println("id="+rs.getInt("id"));
        System.out.println("name="+rs.getString("name"));
    }
} catch (SQLException e) {
    e.printStackTrace();
}finally {
    JdbcUtils.release(conn,pst,rs);
}

6. 事务

ACID原则:

原子性:要么全部完成,要么都不完成

一致性:总数不变

隔离性:多个进程互不干涉

持久性:一旦提交不可逆,持久化到数据库

 

隔离性的问题:

脏读:一个事务读取了另一个没有提交的事务

不可重复读:在同一个事务内,重复读取表中的数据,表数据发生了改变

虚读(幻读):在一个事务内,读取到了别人插入的数据,导致前后读出来的结果不一致

(1)开启事务:conn.setAutoCommit(false);

(2)一组业务执行完毕,提交事务:conn.commit();

(3)在catch语句中显示定义回滚语句:conn.rollback(); 默认失败就会回滚。

conn = JdbcUtils.getConnection(); //获取数据库连接
//关闭数据库的自动提交,自动会开启事务
conn.setAutoCommit(false);//开启事务
 st = conn.createStatement(); //获得sql的执行对象
// sql语句
st.executeUpdate(sql);  //增删改的方法
conn.commit();
} catch (SQLException e) {
  try {
       conn.rollback();
    } catch (SQLException ex) {
         ex.printStackTrace();
    }
        e.printStackTrace();
 }finally {
    JdbcUtils.release(conn,st,rs);
}
}

7.数据库连接池

 使用数据连接池,在项目中不必编写连接数据库的代码

开源数据源实现

DBCP、C3P0、Druid  

posted @ 2022-07-06 09:27  浑浑噩噩一只小迷七  阅读(32)  评论(0)    收藏  举报