数据库
1.初识MySQL
1.1. 数据库分类
关系型数据库 (SQL)
- MySQL,Oracle,Sql Server…
- 通过表和表之间,行和列之间的关系进行数据的存储
非关系型数据库 (NoSQL) Not Only
- Redis, MongDB
- 非关系型数据库,对象存储,通过对象的自身的属性来决定
1.2.三大范式
第一范式(1NF)
原子性:保证每一列不可再分
第二范式(2NF)
前提:满足第一范式
每张表只描述一件事情
第三范式(3NF)
前提:满足第一范式和第二范式
第三范式需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关
而现实中要求相关联的表不超过三个,
为了满足商业需求和性能,我们在设计表的时候,可以故意增添冗余,不一定要遵循规范性的要求
JDBC(重点)
-
数据驱动:声卡,显卡,数据库
我们的程序通过数据库驱动,和数据库打交道 -
JDBC
sun 公司为了简化开发人员的(对数据库的统一)操作,提供了一个(java操作数据库的)规范,俗称JDBC
这些规范的实现由厂商去做
对于开发人员来说,我们只需要掌握JDBC接口的操作即可
java.sql
javax.sql
还需要导入一个数据库驱动包 mysql-connector-java-5.1.47.jar -
第一个JDBC程序
-
创建一个普通的项目
-
导入数据库驱动:先创建一个lib文件夹,导入下载好的数据库驱动包mysql-connector-java-5.1.47.jar,再右击,选择Add as libary…,这时候驱动包才算导入完成。
-
编写测试代码
-
package edu.zb.lesson01;
import java.sql.*;
//我的第一个JDBC程序
public class jdbc {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1. 加载驱动
Class.forName("com.mysql.jdbc.Driver");//固定写法,加载驱动
//2. 用户信息和url 问号前的user是数据库名称
String url = "jdbc:mysql://localhost:3306/user?useUnicode=true&characterEncoding=utf8&useSSL=true";
String username = "root";
String password = "123456";
//3. 连接成功,数据库对象 Connection 代表数据库
Connection connection = DriverManager.getConnection(url,username,password);
//4. 执行SQL的对象 Statement 执行SQL对象
Statement statement = connection.createStatement();
//5. 执行SQL的对象 去 执行SQL,可能存在结果,查看返回结果
String sql = "SELECT * FROM information";//information 是表名
ResultSet resultSet = statement.executeQuery(sql);//返回的结果集,结果集中封装了我们全部的查询出来的结果
while(resultSet.next()){
System.out.println("name="+resultSet.getObject("name"));
System.out.println("age="+resultSet.getObject("age"));
System.out.println("sex="+resultSet.getObject("sex"));
}
//6. 释放连接
resultSet.close();
statement.close();
connection.close();
}
}
步骤总结:
- 加载驱动
- 连接数据库 DriverManger
- 获得执行SQL的对象 Statement
- 获得返回的结果集
- 释放连接
4.statement对象
jdbc中的statement对象用于向数据库发送SQL语句,想完成对数据库的增删改查,只需要通过这个对象向数据库发送增删改查语句即可。
Statement对象的executeUpdate方法,用于向数据库发送增,删,改的SQL语句,executeUpdate执行完后,将会返回一个整数(即增删改语句导致了数据库几行数据发生了变化)。
Statement.executeQuery方法用于向数据库发送查询语句,executeQuery方法返回代表查询结果的ResultSet对象。
代码实现
1.提取工具类:先建立一个db.pproperties文件,写入
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/user?useUnicode=true&characterEncoding=utf8&useSSL=true
username=root
password=123456
再建立一个utils包,创建一个JdbcUtils.java类
package edu.zb.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 (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 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();
}
}
}
}
这样,工具类就写好了,下面的增删改查就可以直接用了
增
package edu.zb.lesson02;
import edu.zb.lesson02.utils.JdbcUtils;
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 information(`name`,`age`,`sex`)\n" +
"VALUES('啊三','22','男')";
int i = st.executeUpdate(sql);
if(i>0){
System.out.println("插入成功!");
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally{
JdbcUtils.release(conn,st,rs);
}
}
}
删
package edu.zb.lesson02;
import edu.zb.lesson02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class TestDelete {
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 = "DELETE FROM information where `name`='啊三'";
int i = st.executeUpdate(sql);
if(i>0){
System.out.println("删除成功");
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally{
JdbcUtils.release(conn,st,rs);
}
}
}
改
package edu.zb.lesson02;
import edu.zb.lesson02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class TestUpdate {
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 = "UPDATE information set `age`='30' WHERE `name`='张三'";
int i = st.executeUpdate(sql);
if(i>0){
System.out.println("更新成功");
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally{
JdbcUtils.release(conn,st,rs);
}
}
}
查(和前三个不一样)
package edu.zb.lesson02;
import edu.zb.lesson02.utils.JdbcUtils;
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 information where `name`='张三'";
rs = st.executeQuery(sql);//查询完毕会返回一个结果集
while(rs.next()){
System.out.println(rs.getObject("age"));
System.out.println(rs.getObject("sex"));
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
5.PrepareStatement对象
PrepareStatement 可以防止SQL注入,效率更好!
1.新增
package edu.zb.lesson03;
import edu.zb.lesson02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class TestInsert {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement st = null;
try {
conn = JdbcUtils.getConnection();
//区别:使用?占位符代表参数
String sql = "insert into information(`name`,`age`,`sex`)"+"values(?,?,?)";
st = conn.prepareStatement(sql);//预编译SQL,先写SQL,然后不执行
//手动给参数赋值
st.setString(1,"狂神");
st.setString(2,"16");
st.setString(3,"女");
//执行
int i = st.executeUpdate();
if(i>0){
System.out.println("插入成功");
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally{
JdbcUtils.release(conn,st,null);
}
}
}
2.删除
package edu.zb.lesson03;
import edu.zb.lesson02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class TestDelete {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement st = null;
try {
conn = JdbcUtils.getConnection();//获取数据库连接
String sql = "delete from information where `name`=?";
st = conn.prepareStatement(sql);//预编译SQL,先写SQL,然后不执行
//手动赋值
st.setString(1,"狂神");
//执行
int i = st.executeUpdate();
if(i>0){
System.out.println("删除成功!");
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
JdbcUtils.release(conn,st,null);
}
}
}
3.更新
package edu.zb.lesson03;
import edu.zb.lesson02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class TestUpdate {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement st = null;
try {
conn = JdbcUtils.getConnection();//获取数据库连接
String sql = "UPDATE information set `age`=? where `name`=?";
st = conn.prepareStatement(sql);
//给参数赋值
st.setString(1,"20");
st.setString(2,"张三");
int i = st.executeUpdate();
if(i>0){
System.out.println("更新成功!");
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
4.查询
package edu.zb.lesson03;
import edu.zb.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 information where `name`=? ";
st = conn.prepareStatement(sql);
//赋值
st.setString(1,"张三");
rs = st.executeQuery();
if(rs.next()){
System.out.println(rs.getString("age"));
System.out.println(rs.getString("sex"));
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally{
JdbcUtils.release(conn,st,rs);
}
}
}
6.使用idea连接数据库
连接成功后,可以选择数据库
双击数据库查看
更新数据(更新完后要点击绿色箭头DB才能成功)
写SQL语句
7.事务
要么都成功,要么都失败
ACID原则
原子性:要么全部完成,要么都不完成
一致性:总数不变
隔离性:多个进程互不干扰
持久性:一旦提交不可逆,持久化到数据库了
隔离性的问题:
脏读:一个事务读取了另一个没有提交的事务
不可重复读:在同一个事务内,重复读取表中的数据,表数据发生了改变
虚读(幻读):在一个事务内,读取到了别人插入的数据,导致前后读出来的结果不一致
代码实现
1.开启事务 conn.setAutoCommit(false)
2.一组业务执行完毕,提交事务
3.可以在catch语句中显示定义回滚语句,但默认失败就会回滚
package edu.zb.lesson04;
import edu.zb.lesson02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class TestTransaction {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement st = 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();
String sql2 = "update account set money = money+100 where name='B'";
st = conn.prepareStatement(sql2);
st.executeUpdate();
//业务完毕,提交事务
conn.commit();
System.out.println("成功!");
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally{
JdbcUtils.release(conn,st,null);
}
}
}
8.数据库连接池
数据库连接----执行完毕----释放
连接----释放 十分浪费系统资源
池化技术:准备一些预先的资源,过来就连接预先准备好的
最小连接数:
最大连接数:
等待超时:
编写连接池,实现一个接口 DataSource
开源数据源实现
DBCP
C3P0
Druid : 阿里巴巴的
使用了这些数据库连接池之后,我们在项目中就不需要编写连接数据库的代码了!
DBCP
需要用到的jar包
commons-dbcp-1.4, commons-pool-1.6