1、数据库驱动
电脑驱动:声卡、显卡等等
我们的数据库会通过数据库驱动,和数据库打交道。
2、JDBC
sun公司为了简化开发人员的操作(对数据库的统一),提供了一个(java操作数据库)规范,俗称JDBC。
这些规范的实现由具体的厂商去做。
开发人员只需要掌握JDBC接口的操作即可。
3、第一个JDBC程序
步骤总结:
1、加载驱动
2、连接数据库 DriverManager
3、获得执行sql的对象 Statement
4、获得返回的结果
5、释放连接
public class JDBCDemo {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1、加载驱动
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
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 connection = DriverManager.getConnection(url, username, password);
//4、获得执行sql的对象 Statement执行sql对象
Statement statement = connection.createStatement();
//5、执行sql的对象 去执行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"));
System.out.println("==================================");
}
//6、释放连接
resultSet.close();
statement.close();
connection.close();
}
}
DriverManager(驱动程序管理器)
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
Class.forName("com.mysql.jdbc.Driver");//固定写法,加载驱动
Connection connection = DriverManager.getConnection(url, username, password);
//connection(连接) 代表数据库
connection.setAutoCommit();//数据库自动提交
connection.commit();//事务提交
connection.rollback();//事务回滚
url
String url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true";
// mysql -- 3306
//语法:协议://主机地址:端口号/数据库名?参数1&参数2&参数3
// oralce -- 1521 //jdbc:oracle:thin:@localhost:1521:sid
Statement(声明) 执行sql的对象 PrepareStatement 执行SQL 的对象
String sql = "SELECT * FROM users"; // 编写SQL
statement.executeQuery(); //查询操作返回 ResultSet
statement.execute(); // 执行任何SQL
statement.executeUpdate(); // 更新、插入、删除。都是用这个,返回一个受影响的行数
ResultSet(结果集) 查询的结果集:封装了所有的查询结果
- 获得指定的数据类型
resultSet.getObject(); // 在不知道列类型的情况下使用
// 如果知道列的类型就使用指定的类型 resultSet.getString();
resultSet.getInt();
resultSet.getFloat();
resultSet.getDate();
resultSet.getObject();
- 遍历,指针
resultSet.beforeFirst(); // 移动到最前面
resultSet.afterLast(); // 移动到最后面
resultSet.next(); //移动到下一个数据
resultSet.previous(); //移动到前一行
resultSet.absolute(row); //移动到指定行
释放资源
//6、释放连接
resultSet.close();
statement.close();
connection.close(); // 耗资源,用完关掉!
4、statement对象
Jdbc中的statement对象用于向数据库发送SQL语句,想完成对数据库的增删改查,只需要通过这个对象
向数据库发送增删改查语句即可。
Statement对象的executeUpdate方法,用于向数据库发送增、删、改的sql语句,executeUpdate执行
完后,将会返回一个整数(即增删改语句导致了数据库几行数据发生了变化)。
Statement.executeQuery方法用于向数据库发送查询语句,executeQuery方法返回代表查询结果的
ResultSet对象。
CRUD操作-create
使用executeUpdate(String sql)方法完成数据添加操作,示例操作:
Statement st = conn.createStatement();
String sql = "insert into user(….) values(…..) ";
int num = st.executeUpdate(sql);
if(num>0){
System.out.println("插入成功!!!");
}
CRUD操作-delete
使用executeUpdate(String sql)方法完成数据删除操作,示例操作:
Statement st = conn.createStatement();
String sql = "delete from user where id=1";
int num = st.executeUpdate(sql);
if(num>0){
System.out.println(“删除成功!!!");
}
CRUD操作-update
使用executeUpdate(String sql)方法完成数据修改操作,示例操作:
Statement st = conn.createStatement();
String sql = "update user set name='' where name=''";
int num = st.executeUpdate(sql);
if(num>0){
System.out.println(“修改成功!!!");
}
CRUD操作-read
使用executeQuery(String sql)方法完成数据查询操作,示例操作:
Statement st = conn.createStatement();
String sql = "select * from user where id=1";
ResultSet rs = st.executeQuery(sql);
while(rs.next()){
//根据获取列的数据类型,分别调用rs的相应方法映射到java对象中
}
代码实现
在src下建立资源文件db.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbcstudy? useUnicode=true&characterEncoding=utf8&useSSL=true
username=root
password=123456
1、提取工具类
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 is = jdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
Properties properties = new Properties();
properties.load(is);
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 (conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (st != null){
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
2、编写增删改的方法: executeUpdate
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,'kuangshen','123456','24736743@qq.com','2020-01-01')";
int i = st.executeUpdate(sql);//返回的是改变的行数
if (i>0){
System.out.println("插入成功!");
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
jdbcUtils.release(conn,st,rs);
}
}
}
3、编写查询的方法 executeQuery
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= "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会存在漏洞,会被攻击导致数据泄露
public class sql注入 {
public static void main(String[] args) {
//login("kuangshen","123456")
login("'or'1=1","'or'1=1");//技巧
}
//登录业务
public static void login(String username,String password){
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
conn = jdbcUtils.getConnection();
st = conn.createStatement();
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"));
System.out.println("========");
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
jdbcUtils.release(conn,st,rs);
}
}
}
5、PreparedStatement对象
PreparedStatement可以防止sql注入。效率更好
1、新增
public class TestInsert {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = 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,"lijinyang");
st.setString(3,"122122");
st.setString(4,"284734561@qq.com");
//注意: util.Date Java new Date().getTime() 获得时间戳
// sql.Date 数据库 java.sql.Date()
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();
}finally {
jdbcUtils.release(conn,st,rs);
}
}
}
防止sql注入
public class sql {
public static void main(String[] args) {
//login("kuangshen","123456")
login("'or'1=1","'or'1=1");//技巧
}
//登录业务
public static void login(String username,String password){
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try {
conn = jdbcUtils.getConnection();
//prepareStatement 防止sql注入的本质,把传递进来的参数当做字符
//假设其中存在转义字符,比如说 '会被直接转义
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"));
System.out.println("========");
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
jdbcUtils.release(conn,st,rs);
}
}
}
7、使用IDEA连接数据库
8、事务
要么都成功,要么都失败。
ACID原则
原子性:要么全部完成,要么都不完成。
一致性:总数不变
隔离性:多个进程互不干扰
持久性:一旦提交不可逆,持久化到数据库
隔离性的问题:
脏读:一个事务读取了另一个没有提交的事务
不可重复读:在用一个事务,重复读取表中的数据,表数据发生了改变
虚读(幻读):在一个事务内,读取到了别人插入的数据,导致前后读出来结果不一致
9、数据库连接池
池化技术:准备一些预先的资源,过来就连接预先准备好的
最小连接数:10
最大连接数:15
等待超时:100ms
编写连接池,实现一个接口 DataSource