1.数据库多表之间的关系
2.上述关系之间的范式
- 注意:一对多的关系是在多的一方建立外键,指向一的一方的主键
- 注意:多对多的关系中,需要建立第三个表,其中至少有两个内容,且分别指向另外两个表的主键
- 创作唯一外键的时候,注意要求是外键需要建立唯一外键(unique)
数据库事务
- 概念,一个包含多个步骤的业务操作,被事务管理,那么这些操作可以一起执行,要么同时成功, 要么同时失败
- 操作:
- 开启事务:start transaction;
- 回滚:rollback;(防止运行到一半出现错误)
- 提交:commit;
* 如果我们要手动提交,那么要先开启事务,再提交
* 自动提交的话,就只需要一条DML语句mysql就会自动帮助提交一次事务
* 查看现在是自动提交还是手动提交的方法
* select @@autocommit ;其默认结果是1
* set @@autocommit = 0;可以自己设置成0 - 注意:如果是手动提交的话,那么我们修改的数据,如果没有commit那么,只是会临时改变,但是重启mysql后,又会回到原处
- 事物的四大特征
- 原子性:不可分割的最小操作单位,要么同时成功,有么同时失败
- 持久性:当食物提交或回滚后,数据库持久化的保存数据
- 隔离性:多个事物之间,相互独立
- 一致性:实务操作前后,数据总量不变
JDBC
- Java DataBase Connectivity Java 数据库连接,java连接数据库;其本质是官方定义的一套操作所有关系行动数据库的规则,即接口。各个数据库厂商去实现这套接口,提供数据库驱动的jar包。我们可以使用这套接口(JDBC)变成,真正执行的代码是驱动jar包中的实现类
- JDBC,定义了一套操作所有关系型数据库的规则(接口)
- JDBC快速入门
public static void main(String[] args) throws Exception {
//1.导入jar包
//2.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//3.获取数据库链接对象
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/student11","root","0916");
//4.定义SQL语句
String sql = "update score set math = 100 where id = 1";
//5.获取执行SQL的对象
Statement stmt = conn.createStatement();
//6.执行SQL;
int count = stmt.executeUpdate(sql);
//7.处理结果
System.out.println(count);
//8.释放资源
stmt.close();
conn.close();
}
- 导入jar包的时候, 不要忘记将jar包所在的包,Add As library
用到的这些类都是借口
- DriverManager:驱动管理对象
- 功能:
1. 注册驱动(DM里面有方法):告诉应该用的是哪一个数据库的驱动jar包
static void registerDriver(Driver driver):注册于给定的驱动程序 DriverManager
写代码使用的却是:Class.forName(“com.mysql.jdbc.Driver”);其中里面含有静态代码块
注意:在mysql5之后的驱动jar包可以省略注册驱动的步骤Class.forName(“com.mysql.jdbc.Driver”);
2. 获取数据库连接
* 方法:static Connection getConnection(String url ,String user, String password)
* 参数:
* url:指定连接的路径
- 语法:jdbc:mysql://IP地址(域名):端口号、数据库名称
- 例子:jdbc:mysql”//localhost:3306/db3
- 细节:如果链接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为: jdbc : msql 😕//数据库名称
- user
- password - Connection(接口):数据库连接对象
1. 功能:
1. 获取SQL的对象
- Statement createStatement()
- PreparedStatement prepareStatement(String SQL)
2. 管理事务 :
- 开启事务:void setAutoCommit(boolean autoCommit): 调用该方法设置参数为false,级开启事务
- 提交事务:commit()
- 回滚事务:rollback() - Statement:执行SQL的对象
1. 执行sql
- boolean execute (String sql) : 可以执行任意的sql(只做了解即可)
- int executeUpdate(String sql) : 执行DML(insert、 update、 delete)语句、DDL(对表和库进行)(create, alter , drop)语句;【注意:返回值是影响的行数,可以用以判断是否执行成功】
- ResultSet executeQuery(String sql) :执行DQL(select)语句
- 练习
1. 对一个表,添加一条记录
2. 修改记录
3. 删除记录
public static void main(String[] args) {
Statement stmt = null;
Connection conn= null;
try {
//1. 注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2. 定义sql
String sql = "insert into student1 values(2,'五liu7',36)";
//3. 获取Connection对象
conn = DriverManager.getConnection("jdbc:mysql:///student11", "root", "0916");
//4. 获取执行SQL的对象 Statement
stmt = conn.createStatement();
//5. 执行SQL
int count = stmt.executeUpdate(sql);
//6. 处理结果
System.out.println(count);
if( count > 0 ){
System.out.println("添加成功! ");
}else{
System.out.println("添加失败! ");
}
}catch (SQLException throwables) {
throwables.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}finally{
// stmt.close(); 不可这样
// 避免空指针异常
//7. 释放资源
//避免空指针异常
if (stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
-
ResultSet:结果集对象(表的列就是结果集对象)
- next():游标向下移动一行
- getXxx(参数):获取数据
* XXX:代表数据类型, 如: int getInt(), String getString()
* 参数:
1. int:代表列的编号,从1开始 如: getString(1)
2. String:代表列的名称 如: getDouble (“balance")
* 注意:
* 步骤如下
- 游标向下移动一行(游标原来在第一行之前)
- 判断是否有数据
- 获取数据(故:可以用while来判断游标是否是在最后一行末尾)* 练习: 1. 查询一个表的数据,将数据封装为对象,然后装在集合,返回 2. 敌营类 3. 定义方法 public List<emp> findAll(){ } 4. 实现方法 select * from emp;
public class EmpDemo006 {
public static void main(String[] args) {
List<Emp> list = new EmpDemo006().findAll();
System.out.println(list);
System.out.println(list.size());
}
/**
* 查询所有emp对象
* @return
*/
public List<Emp> findAll(){
Statement stmt = null;
Connection conn = null;
ResultSet rs = null;
List<Emp> list = null;
try {
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
conn = DriverManager.getConnection("jdbc:mysql:///teachingmanagement", "root", "0916");
//3.定义sql
String sql = "select * from student";
//4.获取执行SQL的对象
stmt = conn.createStatement();
//5.执行SQL
rs = stmt.executeQuery(sql);
//6.遍历结果集,封装对象,装载集合
Emp emp = new Emp();
list = new ArrayList<Emp>();
while(rs.next()) {
int stu_id = rs.getInt("stu_id");
String name = rs.getString("name");
String sex = rs.getString("sex");
String birthday = rs.getString("birthday");
int primary_score = rs.getInt("primary_score");
int department_id = rs.getInt("department_id");
//创建emp对象
emp = new Emp();
emp.setStu_id(stu_id);
emp.setName(name);
emp.setSex(sex);
emp.setBirthday(birthday);
emp.setPrimary_score(primary_score);
emp.setDepartment_id(department_id);
//装载集合
list.add(emp);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}finally{
if( rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if( stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if( conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return list;
}
注意:上面的这些方法,重复度太高,想要通过一个工具类,将代码进行简化
抽取JDBC工具类:JDBCUtils
- 目的:简化书写
- 分析:
1. 注册驱动抽取
2. 抽取一个方法获取连接对象
* 需求:不想传递参数,还得保证工具类的通用性
* 解决方法:配置文件
jdbc.properties
url =
user =
password =
url = jdbc:mysql:///teachingmanagement
user = root
password = 0916
driver = com.mysql.jdbc.Driver
登录练习
* 需求:
1. 通过键盘录入用户名和密码
2. 判断用户是否登录成功
* select * from user where username = " " and password = " " ;
* 如果这个SQL有查询结果,则成功,否则失败
* 步骤
1. 创建数据库表 user
2. 将properties中的数据库名称更改
3. 创建一个新的boolean方法(含有用户名和密码的字符参数)
1. 先判断用户名和密码不是空,是则返回false
2. 获取连接
3. 定义SQL
4. 获取执行SQL的对象
5. 执行查询
6. 判断
7. psvm中进行键盘录入,接受用户名和密码
8. psvm中调用方法
9. 然后判断并输出
- 抽取一个方法来释放资源
- PreparedStatement:执行SQL的对象,但是比其父类Statement功能更强大
- SQL注入问题:在拼接SQL时,有一些SQL的特殊关键字参与字符串的拼接,会造成安全性问题
1. 输入用户名随便,输入密码: a’ or ‘a’ = 'a
2. sql:select * from user where username = ‘dsajidjowjdio’ and password = ‘a’ or ‘a’ = ‘a’ - 解决SQL注入问题:使用PreparedStatement对象来解决
- SQL注入问题:在拼接SQL时,有一些SQL的特殊关键字参与字符串的拼接,会造成安全性问题
数据库连接池
- Spring JDbc:
- 概念:一个容器(集合),存放数据库连接的容器
- 过程:当系统初始化好后,容器被创建,容器中会申请一些链接对象,当用户访问数据库时,从容器中获取链接对象,用户访问完后,会将链接对象归还给容器
- 好处:节约系统的资源,高效
- 实现:
1. 标准接口:DataSource javax.sql包下的
2. 获取连接诶:getConnection()
3. 归还链接:如果连接对象COnnection是从连接池中获取的,那么调用Connection.close方法,则不会再关闭连接了,而是归还链接
4. 用数据库厂商来实现
5. C3P0:数据库连接池技术
6. Druid:数据库连接池实现技术,有阿里巴巴提供的(性能高) - C3P0使用步骤
1. 导入jar包
2.