文章目录
8.权限管理和备份
8.1 用户管理
SQLyog选择小人,添加删除
SQL命令操作
-- ================== 用户权限 =================
-- 创建用户
CREATE USER xiaoai IDENTIFIED BY '123456'
-- 修改当前用户密码
SET PASSWORD =PASSWORD('123456')
-- 修改指定用户密码
SET PASSWORD FOR xiaoai=PASSWORD('111111')
-- 重命名
RENAME USER xiaoai TO xiaoai2
-- 用户授权(不能获取授权权限)
GRANT ALL PRIVILEGES ON *.* TO xiaoai2
-- 查询权限
SHOW GRANTS FOR xiaoai2
-- 撤销权限
REVOKE ALL PRIVILEGES ON *.* FROM xiaoai2
-- 删除用户
DROP USER xiaoai
8.2 备份
为什么?
- 保证重要数据不丢失
- 数据转移
备份方式
- 直接拷贝物理文件
- 使用工具SQLyog手动导出
- 使用命令行导出
mysqldump -主机 -用户 -密码 表明 >导出地址
9.规范数据库设计
9.1为什么要设计
数据库比较复杂
糟糕的:
- 数据冗余
- 插入删除麻烦
- 程序性能差
良好的
-
节省空间
-
保证数据完整性
-
方便开发系统
数据库设计流程 -
分析需求
-
概要设计,关系图设计
设计步骤 -
收集信息,分析需求。
用户表(用户登录,注销,用户的个人信息,写博客,创建分类);
分类表
文章表
友情链接
自定义表 -
标识实体
9.2 为什么要规范化
- 信息重复
- 更新异常
- 插入一场
- 删除异常
三大范式
第一范式:
原子性,保证每一列不可再分
第二范式:
前提满足第一范式,每张表只描述一件事情
第三范式:
前提满足第一范式和第二范式, 表的每一列和主键直接相关
规范性和性能的关系:
关联查询的表不得超过3张
- 商业化中,数据库的性能更重要
- 故意增加冗余字段,避免多表查询
- 故意增加计算列(也可增加索引)
JBDC(重点)
10.1 数据库驱动
驱动:声卡、显卡、数据库
应用程序----驱动----数据库
10.2 JDBC
SUN公司为了简化开发人员对数据库的统一操作,提供了一个java操作数据库的规范,俗称JDBC
开发人员只需要学习JDBC接口的操作
java.sql
javax.sql
10.3 JDBC程序
1.创建普通项目
2.导入数据库驱动
3.编写测试代码
package com.kuang.lesson01;
import java.sql.*;
public class JdbeDemo01 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1.加载驱动
Class.forName("com.mysql.jdbc.Driver");//固定写法
//2.用户信息和url
String url="jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true";
String username="root";
String password="123456";
//3.连接成功,数据库对象
Connection connection = DriverManager.getConnection(url, username, password);
//4.执行SQL的对象
Statement statement = connection.createStatement();
//5.执行SQL
String sql="SELECT * FROM users";
ResultSet resultSet = statement.executeQuery(sql);//
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("birth="+resultSet.getObject("birthday"));
}
//6.释放连接
resultSet.close();
statement.close();
}
}
步骤总结:
1.加载驱动
2.连接数据库Driver Manager
3.获取执行sql的对象,statement
4.获得返回的结果集(查询)
5.释放连接
Driver Manager
加载驱动
获取连接
//1.加载驱动
Class.forName("com.mysql.jdbc.Driver");//固定写法
//connection代表数据库
Connection connection = DriverManager.getConnection(url, username, password);
connection.rollback();//回滚
connection.commit();//提交
connection.setAutoCommit();//自动提交
URL
String url="jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true";
//想象成http
//jdbc:mysql://localhost:3306/数据库名?参数
//oralce 1521
//jdbc:oracle:thin:@localhost:1521:sid
statement执行sql的对象,preparestatement
String sql="SELECT * FROM users";
statement.executeUpdate();//更新插入和删除
statement.execute();//执行任何sql
resultset 封装所有的查询结果
获得指定的数据类型;
resultSet.getObject("id"));
遍历,指针:
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("birth="+resultSet.getObject("birthday"));
}
10.4 statement对象
增删改update
差quary
代码:
1.提取工具类
package com.kuang.lesson02.utils;
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 (IOException | ClassNotFoundException 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();
}
}
}
}
2.编写增删改的方法
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(6,'kuangshen','123456','123@qq.com','2020-11-11')";
int i = st.executeUpdate(sql);
if(i>0){
System.out.println("插入成功");
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
JdbcUtils.release(conn,st,rs);
}
}
}
3.查询excuteQuary
package com.kuang.lesson02.utils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class TestSelect {
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="select * from users where id=1";
rs = st.executeQuery(sql);//查询
while (rs.next()){
System.out.println(rs.getString("NAME"));
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
JdbcUtils.release(conn,st,rs);
}
}
}
SQL注入:
SQL存在漏洞,被攻击,导致数据泄露,
采用不合法的字符串。
package com.kuang.lesson02.utils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class SQL注入 {
public static void main(String[] args) {
//login("kuangshen","123456");
login("'or'1=1","123456");
}
//登陆业务
public static void login(String username,String password){
Connection conn=null;
Statement st=null;
ResultSet rs=null;
try {
conn = JdbcUtils.getConnection();
st=conn.createStatement();
//sql
String sql="select * from users where `NAME`='"+username+"' AND `password`='"+password+"'";
rs = st.executeQuery(sql);//查询
while (rs.next()){
System.out.println(rs.getString("NAME"));
System.out.println(rs.getString("password"));
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
JdbcUtils.release(conn,st,rs);
}
}
}
10.5. PreparedStatement
防止SQL注入,效率更高
1.添加
package com.kuang.lesson03;
import com.kuang.lesson02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Date;
public class TestUpdate {
public static void main(String[] args) {
Connection conn=null;
PreparedStatement st=null;
try {
conn=JdbcUtils.getConnection();
// 区别
//String sql="INSERT INTO users (id,`NAME`,`PASSWORD`,email,birthday) values(?,?,?,?,?)";
String sql="update users set `NAME`=? where id=?";
st=conn.prepareStatement(sql);
//手动参数赋值
st.setString(1,"wang");
st.setInt(2,1);
//执行
int i=st.executeUpdate();
if(i>0){
System.out.println("更新成功");
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
2.删除
package com.kuang.lesson03;
import com.kuang.lesson02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Date;
public class TestDelete {
public static void main(String[] args) {
Connection conn=null;
PreparedStatement st=null;
try {
conn= JdbcUtils.getConnection();
// 区别
// String sql="INSERT INTO users (id,`NAME`,`PASSWORD`,email,birthday) values(?,?,?,?,?)";
String sql="delete from users where id=?";
st=conn.prepareStatement(sql);
//手动参数赋值
st.setInt(1,4);
//执行
int i=st.executeUpdate();
if(i>0){
System.out.println("删除成功");
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
3.修改
package com.kuang.lesson03;
import com.kuang.lesson02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
public class TestInsert {
public static void main(String[] args) {
Connection conn=null;
PreparedStatement st=null;
try {
conn=JdbcUtils.getConnection();
// 区别
String sql="INSERT INTO users (id,`NAME`,`PASSWORD`,email,birthday) values(?,?,?,?,?)";
st=conn.prepareStatement(sql);
//手动参数赋值
st.setInt(1,4);
st.setString(2,"mabao");
st.setString(3,"123456");
st.setString(4,"123@qq.com");
st.setDate(5,new java.sql.Date(new Date().getTime()));
//执行
int i=st.executeUpdate();
if(i>0){
System.out.println("出入成功");
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
4.查询
package com.kuang.lesson03;
import com.kuang.lesson02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class TestSelect {
public static void main(String[] args) {
Connection conn=null;
PreparedStatement st=null;
ResultSet rs=null;
try {
conn=JdbcUtils.getConnection();
String sql="select * from users where id=?";
st=conn.prepareStatement(sql);//预编译
st.setInt(1,1);//传递参数
rs=st.executeQuery();//执行
if(rs.next()){
System.out.println(rs.getString("NAME"));
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
JdbcUtils.release(conn,st,rs);
}
}
}
5.防止sql注入
package com.kuang.lesson02.utils;
import java.sql.*;
public class SQL注入 {
public static void main(String[] args) {
//login("kuangshen","123456");
login("'or'1=1","123456");
}
//登陆业务
public static void login(String username,String password){
Connection conn=null;
PreparedStatement st=null;
ResultSet rs=null;
try {
conn = JdbcUtils.getConnection();
//PreparedStatement防止sql注入的本质,把传递进来的参数当作字符
//假设其中存在转义字符,就直接忽略
//Mybatis
String sql="select * from users where `NAME`=? and `password`=?";
st=conn.prepareStatement(sql);
st.setString(1,username);
st.setString(2,password);
rs=st.executeQuery();
while (rs.next()){
System.out.println(rs.getString("NAME"));
System.out.println(rs.getString("password"));
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
JdbcUtils.release(conn,st,rs);
}
}
}
10.7 使用IDEA连接数据库
连接成功后,可以选择数据库
更新数据:db
10.8 事务
要么都成功,要么都失败
acid
原子性
一致性
隔离性
持久性
隔离性的问题
脏读:一个事务读取了另一个没有提交的事务
不可重复读:同一个事务内重复读取表中的数据
虚读:在一个事务内读取到了别人插入的数据,导致前后结果不一致
代码实现
1.开启事务
2.执行完毕,提交事务
3.失败回滚
package com.kuang.lesson04;
import com.kuang.lesson02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class TEstTransaction {
public static void main(String[] args) {
Connection conn=null;
PreparedStatement st=null;
ResultSet rs=null;
try {
conn=JdbcUtils.getConnection();
//关闭自动提交,自动开启事务
conn.setAutoCommit(false);
String sql1="update account set money=money-100 where name='A'";
st=conn.prepareStatement(sql1);
st.executeUpdate();
int x=1/0;//报错,如果失败,默认回滚
String sql2="update account set money=money+100 where name='B'";
st=conn.prepareStatement(sql2);
st.executeUpdate();
//提交事务
conn.commit();
System.out.println("成功");
} catch (SQLException e) {
try {
conn.rollback();
} catch (SQLException ex) {
ex.printStackTrace();
}
e.printStackTrace();
}finally {
JdbcUtils.release(conn,st,rs);
}
}
}
10.9 数据库连接池
连接释放操作十分浪费系统资源
池化技术:准备一些预先的资源,过来就连接预备好的
常用连接数
最小连接数
最大连接数:最高承载上限
等待超时:100ms
编写连接池,实现一个接口,datasource
开源数据源实现
dbcp
c3p0
druid:阿里巴巴
使用了这些数据库连接池之后,就不用编写连接数据库的代码了
dbcp
需要用的jar包
commons-dbcp-1.4 commons-pool-1.6
c3p0
需要用的jar包