初始JavaWeb
什么是JavaWeb
- Web:全球广域网,也称为万维网(www),能够通过浏览器访问的网站
- JavaWeb:是用Java技术来解决相关web互联网领域的技术栈
- 网页:展现数据
- 数据库:存储和管理数据
- JavaWeb程序:逻辑处理
一、JDBC
1.1、JDBC简介
JDBC概念:
- JDBC就是使用Java语言操作关系型数据库的一套API
- 全称:(Java DataBase Connectivity ) Java数据库连接
JDBC本质:
- 官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口
- 各个数据库厂商去实现这套接口,提供数据库驱动jar包
- 我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类
JDBC好处:
- 各数据库厂商使用相同的接口,Java代码不需要针对不同数据库分别开发
- 可随时替换底层数据库,访问数据库的Java代码基本不变
初体验
package com.Smulll.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
public class JDBCdome {
public static void main(String[] args) throws Exception {
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
String url = "jdbc:mysql://127.0.0.1:3306/test1";
String username = "root";
String password = "123456";
Connection conn = DriverManager.getConnection(url, username, password);
//3.定义sql
String sql = "insert into dept values (null,'项目部')";
//4. 获取执行SQL的对象 Statement
Statement stmt = conn.createStatement();
//5. 执行sql
int count = stmt.executeUpdate(sql);//受影响的行数
//6. 受处理的结果
System.out.println(count);
//7.释放资源
stmt.close();
conn.close();
}
}
1.2、API详解-DriverManager
- DriverManager(驱动管理类)作用:
- 注册驱动
- 获取数据库连接
- 注册驱动
Class.forName("com.mysql.jdbc.Driver");
提示:
- MySQL 5之后的驱动包,可以省略注册驱动的步骤
- 自动加载jar包中META-INF/services/java.sql.Driver文件中的驱动类
- 获取链接
static Connection getConnection (String url,String user,String password)
- 参数:
- url:连接路径
- 语法:
jdbc:mysql://ip地址(域名):端口号/数据库名称?参数键值对1&参数键值对2...
- 示例:
jdbc:mysql://127.0.0.1:3306/db1
- 细节:
- 如果连接的是本机mysql服务器,并且mysqlI服务默认端口是3306,则ur可以简写为:
jdbc:mysql///数据库名称?参数键值对
- 配置
useSSL=false
参数,禁用安全连接方式,解决警告提示
- 如果连接的是本机mysql服务器,并且mysqlI服务默认端口是3306,则ur可以简写为:
- 语法:
- user:用户名
- password:密码
- url:连接路径
package com.Smulll.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
public class JDBCdemo2_DriverManager {
public static void main(String[] args) throws Exception {
//省略注册驱动步骤
String url = "jdbc:mysql:///test1?useSSL=false";//解决警告提示
String username = "root";
String password = "123456";
Connection conn = DriverManager.getConnection(url, username, password);
String sql = "insert into dept values (null,'项目部')";
Statement statement = conn.createStatement();
int i = statement.executeUpdate(sql);
System.out.println(i);
statement.close();
conn.close();
}
}
1.3、API详解-Connection
- Connection(数据库连接对象)作用:
- 获取执行SQL的对象
- 管理事务
-
获取执行SQL的对象
- 普通执行SQL对象
Statement createStatement()
- 预编译SQL的执行SQL对象:防止SQL注入
PreparedStatement prepareStatement (sql)
- 执行存储过程的对象
CallableStatement prepareCall (sql)
-
事务管理
- MySQL事务管理
开启事务:BEGIN; / START TRANSACTION;
提交事务:COMMIT;
回滚事务:ROLLBACK;
MySQL默认自动提交事务 - JDBC事务管理:Connection接口中定义了3个对应的方法
开启事务:setAutoCommit(boolean autoCommit)
: true为自动提交事务;false为手动提交事务,即为开启事务
提交事务:commit()
回滚事务:rollback()
- MySQL事务管理
package com.Smulll.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
public class JDBCdemo3_Connet {
public static void main(String[] args) throws Exception {
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
String url = "jdbc:mysql://127.0.0.1:3306/test1?useSSL=false";
String username = "root";
String password = "123456";
Connection conn = DriverManager.getConnection(url, username, password);
//3.定义sql
String sql1 = "insert into dept values (null,'1')";
String sql2 = "insert into dept values (null,'2')";
//4. 获取执行SQL的对象 Statement
Statement stmt = conn.createStatement();
//使用try-catch块来抛出异常
try {
//开启手动管理事务
conn.setAutoCommit(false);
//5. 执行sql
int count1 = stmt.executeUpdate(sql1);//受影响的行数
//6. 受处理的结果
System.out.println(count1);
int count2 = stmt.executeUpdate(sql2);//受影响的行数
// 6. 受处理的结果
System.out.println(count2);
//提交事务
conn.commit();
} catch (Exception e) {
//如果出现异常回滚事务
conn.rollback();
}
//7.释放资源
stmt.close();
conn.close();
}
}
1.4、API详解-Statement
- Statement作用:
- 执行SQL语句
执行SQL语句
int executeUpdate(sql):执行DML、DDL语句
返回值:
DML语句影响的行数
DDL语句执行后,执行成功也可能返回0
ResultSet executeQuery(sql): 执行DQL语句
返回值:
ResultSet结果集对象
package com.Smulll.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import org.junit.Test;
public class JDBCdemo4_Statement {
@Test
public void testDML() throws Exception {
//省略注册驱动步骤
String url = "jdbc:mysql:///test1?useSSL=false";//解决警告提示
String username = "root";
String password = "123456";
Connection conn = DriverManager.getConnection(url, username, password);
String sql = "insert into dept values (null,'123')";
Statement statement = conn.createStatement();
int i = statement.executeUpdate(sql);
if (i>0){
System.out.println("执行成功~");
}else {
System.out.println("执行失败~");
}
statement.close();
conn.close();
}
@Test
public void testDDL() throws Exception {
//省略注册驱动步骤
String url = "jdbc:mysql:///test1?useSSL=false";//解决警告提示
String username = "root";
String password = "123456";
Connection conn = DriverManager.getConnection(url, username, password);
String sql = "create database bd1";
Statement statement = conn.createStatement();
int i = statement.executeUpdate(sql);
System.out.println(i);
statement.close();
conn.close();
}
}
1.5、API详解-ResultSet
- ResultSet(结果集对象)作用:
- 封装了DQL查询语句结果
ResultSet stmt.executeQuery(sql):执行DQL语句,返回ResultSet对象
- 获取查询结果
boolean next(): (1)将光标从当前位置向前移动一行 (2)判断当前行是否为有效行
返回值:
true:有效行,当前行有数据.
false:无效行,当前行没有数据
xxx getXxx(参数):获取数据
xxx:数据类型;如:int getlnt(参数) ; String getString(参数)
参数:
int:列的编号,从1开始.
String:列的名称
- 使用步骤
- 游标向下移动一行,并判断该行否有数据:
next()
- 获取数据:
getXxx(参数)
- 游标向下移动一行,并判断该行否有数据:
//循环判断游标是否是最后一行末尾
while(rs.next()){
//获取数据
rs.getXxx(参数)
}
代码演示
package com.Smulll.jdbc;
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class JDBCdemo5_ResultSet {
@Test
public void testResultSet() throws Exception {
//省略注册驱动步骤
String url = "jdbc:mysql:///test1?useSSL=false";//解决警告提示
String username = "root";
String password = "123456";
//获取连接
Connection conn = DriverManager.getConnection(url, username, password);
//要执行的SQL语句
String SQL = "select * from dept";
//获取执行SQL的statement对象
Statement statement = conn.createStatement();
//获取查询结果对象
ResultSet rs = statement.executeQuery(SQL);
//循环遍历出所有数据
while (rs.next()){
int id = rs.getInt("id");
String name = rs.getString("name");
//打印出遍历的结果
System.out.println(id);
System.out.println(name);
System.out.println("---------------------------------------------");
}
//关流
rs.close();
statement.close();
conn.close();
}
}
package com.Smulll.jdbc;
import com.Smulll.Pojo.account;
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
public class JDBCdemo5_ResultSetDemo {
@Test
public void testResultSet() throws Exception {
//省略注册驱动步骤
String url = "jdbc:mysql:///test1?useSSL=false";//解决警告提示
String username = "root";
String password = "123456";
//获取连接
Connection conn = DriverManager.getConnection(url, username, password);
//要执行的SQL语句
String SQL = "select * from student";
//获取执行SQL的statement对象
Statement statement = conn.createStatement();
//获取查询结果对象
ResultSet rs = statement.executeQuery(SQL);
//创建一个集合,将查询出的结果存入
List<account> list = new ArrayList<>();
//循环遍历出所有数据
while (rs.next()){
account account = new account();
int id = rs.getInt("id");
String name = rs.getString("name");
int num = rs.getInt("num");
//将结果存入到集合当中
account.setId(id);
account.setName(name);
account.setNum(num);
list.add(account);
}
System.out.println(list);
//关流
rs.close();
statement.close();
conn.close();
}
}
package com.Smulll.Pojo;
public class account {
private int id;
private String name;
private int num;
public account() {
}
public account(int id, String name, int num) {
this.id = id;
this.name = name;
this.num = num;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public String toString() {
return "account{id = " + id + ", name = " + name + ", num = " + num + "}";
}
}
1.6、API详解-PreparedStatement
1.6.1、API详解-PreparedStatement-SQL注入演示
-
PreparedStatement作用:
- 预编译SQL语句并执行:预防SQL注入问题
-
SQL注入
- SQL注入是通过操作输入来修改事先定义好的SQL语句,用以达到执行代码对服务器进行攻击的方法。
package com.Smulll.jdbc;
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class JDBCdemo6_PreparedStatement {
@Test
public void testResultSet() throws Exception {
//省略注册驱动步骤
String url = "jdbc:mysql:///test1?useSSL=false";//解决警告提示
String username = "root";
String password = "123456";
//获取连接
Connection conn = DriverManager.getConnection(url, username, password);
String name = "qweqweqwe";
String pwd = "'or'1'='1";
//要执行的SQL语句
String SQL = "select * from tb_user where name = '"+name+"' and password = '"+pwd+"'";
//获取执行SQL的statement对象
Statement statement = conn.createStatement();
//获取查询结果对象
ResultSet rs = statement.executeQuery(SQL);
if (rs.next()){
System.out.println("执行成功");
}else {
System.out.println("执行失败");
}
//关流
rs.close();
statement.close();
conn.close();
}
}
1.6.2、API详解-PreparedStatement
- PreparedStatement作用:
- 预编译SQL并执行SQL语句
- 获取PreparedStatement 对象
//SQL语句中的参数值,使用?占位符替代
String sql = "select * from user where username = ? and password = ?";
//通过Connection对象获取,并传入对应的sql语句
PreparedStatement pstmt = conn.prepareStatement(sql);
- 设置参数值
PreparedStatement对象:setXxx(参数1,参数2):给?赋值
Xxx:数据类型; 如setInt(参数1,参数2)
参数:
参数1:?的位置编号,从1开始
参数2:?的值
- 执行SQL
executeUpdate();/ executeQuery(); :不需要再传递sql
package com.Smulll.jdbc;
import org.junit.Test;
import java.sql.*;
public class JDBCdemo7_PreparedStatement {
@Test
public void testResultSet() throws Exception {
//省略注册驱动步骤
String url = "jdbc:mysql:///test1?useSSL=false";//解决警告提示
String username = "root";
String password = "123456";
//获取连接
Connection conn = DriverManager.getConnection(url, username, password);
String name = "小明";
String pwd = "123";
//要执行的SQL语句
String SQL = "select * from tb_user where name = ? and password = ?";
//获取执行SQL的statement对象
Statement statement = conn.createStatement();
//获取查询结果对象
PreparedStatement pstm = conn.prepareStatement(SQL);
//通过preparedStatement对象来设置?的值
pstm.setString(1,name);
pstm.setString(2,pwd);
//获取到查询的结果
ResultSet rs = pstm.executeQuery();
if (rs.next()){
System.out.println("执行成功");
}else {
System.out.println("执行失败");
}
//关流
rs.close();
pstm.close();
conn.close();
}
}
1.6.3、API详解-PreparedStatement-原理
- PreparedStatement好处:
- 预编译SQL,性能更高
- 防止SQL注入: 将敏感字符进行转义
-
PreparedStatement预编译功能开启:
useServerPrepStmts=true
-
配置MySQL执行日志(重启mysql服务后生效)
log-output=FILE
general-log=1
general_log_file="D:\mysql.log"
slow-query-log=1
slow_query_log_file="D:\mysql_slow.log"
long_query_time=2
- PreparedStatement原理:
- 在获取PreparedStatement对象时,将sql语句发送给mysql服务器进行检查,编译(这些步骤很耗时)
- 执行时就不用再进行这些步骤了,速度更快
- 如果sql模板一样,则只需要进行一次检查、编译
1.7、数据库连接池
1.7.1、数据库连接池简介
- 数据库连接池是个容器,负责分配、管理数据库连接(Connection)
- 它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;
- 释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏
- 好处:
- 资源重用
- 提升系统响应速度
- 避免数据库连接遗漏
- 标准接口: DataSource
- 官方(SUN)提供的数据库连接池标准接口,由第三方组织实现此接口
- 功能:获取连接
Connection getConnection()
- 常见的数据库连接池:
- DBCP
- C3P0
- Druid
1.7.2、Druid(德鲁伊)连接池
- Druid(德鲁伊)
- Druid连接池是阿里巴巴开源的数据库连接池项目
- 功能强大,性能优秀,是Java语言最好的数据库连接池之一
Druid使用步骤
- 导入jar包 druid-1.1.12.jar
- 定义配置文件
- 加载配置文件
- 获取数据库连接池对象
- 获取链接
package com.Smulll.druid;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.util.Properties;
public class DruidDemo {
public static void main(String[] args) throws Exception {
//1.导入jar包
//2.定义配置文件
//3.加载配置文件
Properties prop = new Properties();
prop.load(new FileInputStream("D:\\Java\\IDEA\\代码文件\\jdbc\\jdbc-dome\\src\\druid.properties"));
//4.获取连接池对象
DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
//5.获取对应的数据库连接 Connection
Connection connection = dataSource.getConnection();
System.out.println(connection);
/*System.out.println(System.getProperty("user.dir"));*/
}
}
配置文件
#驱动位置
driverClassName = com.mysql.jdbc.Driver
#通信地址
url=jdbc:mysql:///test1?useSSL=false
#用户名
username=root
#密码
password=123456
#初始化连接数
initialSize=5
#最大连接数
maxActive=10
#最大等待时间(毫秒)
maxWait=3000
二、JDBC练习
2.1、环境准备
create table tb_brand
(
id int primary key auto_increment,
brand_name varchar(20),
company_name varchar(20),
ordered int,
description varchar(100),
status int
);
insert into tb_brand (brand_name, company_name, ordered, description, status)
values ('三只松鼠','三只松鼠股份有限公司',5,'好吃不上火',0),
('华为','华为技术有限公司',100,'华为就是牛逼',1),
('小米','小米科技有限公司',50,'are you ok',1);
select * from tb_brand;
package com.Smulll.Pojo;
public class brand {
private Integer id;
private String brundName;
private String companyName;
private Integer ordered;
private String description;
private Integer status;
public brand() {
}
public brand(Integer id, String brundName, String companyName, Integer ordered, String description, Integer status) {
this.id = id;
this.brundName = brundName;
this.companyName = companyName;
this.ordered = ordered;
this.description = description;
this.status = status;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getBrundName() {
return brundName;
}
public void setBrundName(String brundName) {
this.brundName = brundName;
}
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public Integer getOrdered() {
return ordered;
}
public void setOrdered(Integer ordered) {
this.ordered = ordered;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String toString() {
return "brand{id = " + id + ", brundName = " + brundName + ", companyName = " + companyName + ", ordered = " + ordered + ", description = " + description + ", status = " + status + "}";
}
}
2.2、查询所有
package com.Smulll.example;
import com.Smulll.Pojo.brand;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.junit.Test;
import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
public class BrandTest {
/*
* 查询所有
* 1. SQL:select* from tb_brand
* 2. 参数:不需要
* 3. 结果:List<brand>
* */
@Test
public void tsetSelectAll() throws Exception {
//获取连接对象
Properties prop = new Properties();
prop.load(new FileInputStream("D:\\Java\\IDEA\\代码文件\\jdbc\\jdbc-dome\\src\\druid.properties"));
//获取连接池对象
DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
//获取对应的数据库连接 Connection
Connection conn = dataSource.getConnection();
//定义SQL
String SQL = "select* from tb_brand";
//获取psmt对象
PreparedStatement psmt = conn.prepareStatement(SQL);
//设置参数
//无参数
//执行SQL
ResultSet rs = psmt.executeQuery();
//处理结果
//创建一个集合收集数据
List list = new ArrayList<brand>();
while (rs.next()) {
//获取到结果
int id = rs.getInt("id");
String brandName = rs.getString("brand_name");
String companyName = rs.getString("company_name");
int ordered = rs.getInt("ordered");
String description = rs.getString("description");
int status = rs.getInt("status");
//创建一个brand对象
brand brand = new brand(id,brandName,companyName,ordered,description,status);
list.add(brand);
}
System.out.println(list);
rs.close();
psmt.close();
conn.close();
}
}
2.3、添加&修改&删除
package com.Smulll.example;
import com.Smulll.Pojo.brand;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.junit.Test;
import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
public class BrandTest_add {
/*
* 添加
* 1. SQL:insert into tb_brand (brand_name, company_name, ordered, description, status) values (?,?,?,?,?)
* 2. 参数:需要
* 3. 结果:bool
* */
@Test
public void tsetadd() throws Exception {
//需要添加的数据
String brandName = "农夫山泉";
String companyName = "哇哈哈有限公司";
int ordered = 1;
String description = "我们不生产水,我们只是大自然的搬运工";
int status = 1;
//获取连接对象
Properties prop = new Properties();
prop.load(new FileInputStream("D:\\Java\\IDEA\\代码文件\\jdbc\\jdbc-dome\\src\\druid.properties"));
//获取连接池对象
DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
//获取对应的数据库连接 Connection
Connection conn = dataSource.getConnection();
//定义SQL
String SQL = "insert into tb_brand (brand_name, company_name, ordered, description, status) values (?,?,?,?,?)";
//获取psmt对象
PreparedStatement psmt = conn.prepareStatement(SQL);
//设置参数
psmt.setString(1,brandName);
psmt.setString(2,companyName);
psmt.setInt(3,ordered);
psmt.setString(4,description);
psmt.setInt(5,status);
//执行SQL
int i = psmt.executeUpdate();
System.out.println(i>0);
psmt.close();
conn.close();
}
}
package com.Smulll.example;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.junit.Test;
import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.Properties;
public class BrandTest_update {
/*
* 修改
* 1. SQL:update tb_brand set brand_name = ?,company_name = ?,ordered = ?,description = ?,status= ? where id = ?
* 2. 参数:需要
* 3. 结果:bool
* */
@Test
public void tsetupdate() throws Exception {
//需要添加的数据
String brandName = "农夫山泉";
String companyName = "哇哈哈有限公司";
int ordered = 100;
String description = "我们不生产水,我们只是大自然的搬运工";
int status = 1;
//获取连接对象
Properties prop = new Properties();
prop.load(new FileInputStream("D:\\Java\\IDEA\\代码文件\\jdbc\\jdbc-dome\\src\\druid.properties"));
//获取连接池对象
DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
//获取对应的数据库连接 Connection
Connection conn = dataSource.getConnection();
//定义SQL
String SQL = "update tb_brand set " +
"brand_name = ?," +
"company_name = ?," +
"ordered = ?," +
"description = ?," +
"status= ? where " +
"id = ?";
//获取psmt对象
PreparedStatement psmt = conn.prepareStatement(SQL);
//设置参数
psmt.setString(1,brandName);
psmt.setString(2,companyName);
psmt.setInt(3,ordered);
psmt.setString(4,description);
psmt.setInt(5,status);
psmt.setInt(6,4);
//执行SQL
int i = psmt.executeUpdate();
System.out.println(i>0);
psmt.close();
conn.close();
}
}
package com.Smulll.example;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.junit.Test;
import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.Properties;
public class BrandTest_delete {
/*
* 删除
* 1. SQL:delete from tb_brand where id = ?
* 2. 参数:需要
* 3. 结果:bool
* */
@Test
public void tsetdelete() throws Exception {
//设置要删除的对象
int a = 6;
//获取连接对象
Properties prop = new Properties();
prop.load(new FileInputStream("D:\\Java\\IDEA\\代码文件\\jdbc\\jdbc-dome\\src\\druid.properties"));
//获取连接池对象
DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
//获取对应的数据库连接 Connection
Connection conn = dataSource.getConnection();
//定义SQL
String SQL = "delete from tb_brand where id = ?";
//获取psmt对象
PreparedStatement psmt = conn.prepareStatement(SQL);
//设置参数
psmt.setInt(1,a);
//执行SQL
int i = psmt.executeUpdate();
System.out.println(i>0);
psmt.close();
conn.close();
}
}