JavaWEB-03-JDBC
内容
JDBC
`JDBC`简介JDBC
`JDBC`快速入门JDBC API
`JDBC API` 详解- 数据库连接池
JDBC
`JDBC`案例
1. JDBC
入门
1.1 概述
概念
JDBC:Java DataBase Connectivity
,Java
数据库连接JDBC
就是使用Java
语言操作关系型数据库的一套API
。Sun
公司和数据库厂商共同制定的一套连接并操作数据库的统一规范(接口),由数据库厂商负责实现(驱动Jar
包);我们使用的时候只需要导入数据库厂商已经实现好的jar
包即可。好处
因为各个数据库厂商都实现了同一套
JDBC
接口规范。- 我们可以使用同一套
Java
代码操作不同的关系型数据库 - 访问数据库的
Java
代码不改变的前提下,替换不同的驱动Jar
包可以轻松更换数据库
- 我们可以使用同一套
我们要怎么做
整体思路:基于
JDBC
定义的规则编码,不用考虑不同数据库之间的差异- 导数对应据库驱动包。
- 基于
JDBC
定义的规则轻松编程。
1.2 quick start
实现步骤
- 导入
Jar
包 - 注册驱动
- 获取连接
- 获取执行者对象
- 执行
SQL
语句,并且接收结果 - 处理结果
- 释放资源
- 导入
演示代码
package com.cy.jdbc; import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.Statement; /**
* JDBC快速入门
*/
public class JDBCDemo { public static void main(String[] args) throws Exception {
//1. 注册驱动 建议写上去
Class.forName("com.mysql.jdbc.Driver");
//2. 获取连接
//url jdbc:mysql:///maven == jdbc:mysql://127.0.0.1:3306/maven
//jdbc:mysql://ip:数据库端口号/数据库名称?添加自定义参数
String url = "jdbc:mysql://127.0.0.1:3306/maven";
String username = "root";
String password = "root";
//Connection 数据库的连接对象
Connection conn = DriverManager.getConnection(url, username, password);
//3. 定义sql
String sql = "update account set money = ? where id = ?";
//4. 获取执行sql的对象 Statement
//Statement stmt = conn.createStatement();
PreparedStatement pps = conn.prepareStatement(sql); pps.setDouble(1,3000);
pps.setInt(2,1); //5. 执行sql
//int count = stmt.executeUpdate(sql);//受影响的行数 执行增删改
int count = pps.executeUpdate(); //6. 处理结果 受影响的行数
System.out.println(count);
//7. 释放资源
pps.close();
conn.close();
}
}
2. jdbc
常用API
2.1 DriverManager
功能1:注册驱动
- 不需要手动调用
DriverManager
的API
注册,而是保证com.mysql.jdbc.Driver
被加载进内存即可。
查看com.mysql.jdbc.Driver
类的源码
package com.mysql.jdbc;
import java.sql.DriverManager;
import java.sql.SQLException;
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
public Driver() throws SQLException {
}
static {
try {
// 在静态代码块中完成了注册驱动的代码
// 我们只要保证Driver被加载进内存,下面的注册驱动的步骤就会自动完成。
/*
Class.forName("com.mysql.jdbc.Driver");
Driver.class //Driver的字节码对象
new Driver(); // 多一个driver对象
*/
/*
在MySQL5以上的版本,注册驱动不需要我们自己做了。
在mysql-connector-java-5.1.47.jar中META-INF下面services下面的
java.sql.Driver文件中,填写了com.mysql.jdbc.Driver全类名
该类的便会自动被加载进内存
*/
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
}
功能2:获取连接对象
static Connection getConnection(url, username, password)
//3.获取连接
// 相当于之前使用mysql工具连接数据库
// 完整格式:jdbc:mysql://ip:数据库端口号/数据库名称?添加自定义参数
// jdbc:mysql://就是协议 相当于 http://
// url连本机 jdbc:mysql://localhost:3306/db2 简化写法jdbc:mysql:///db2
// 可选自定义参数:useSSL=false 不是用SSL加密并取消提示
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1","root","root");
2.2 Connection
就像打电话,一个Connection
对象,就是一通电话。
所以连接又称会话,Session
。
功能1:获取执行者对象
该对象会执行SQL
语句
获取普通执行者对象:
Statement createStatement();
获取预编译执行者对象:
PreparedStatement prepareStatement(String sql);
功能2:控制事务
Connection
中定义了三个方法,用来控制事务。对应MySQL
中的三种操作。
开启:
setAutoCommit(boolean autoCommit);
参数为false,则开启事务。提交:
commit();
回滚:
rollback();
功能3:释放资源
close();
演示代码
package com.cy.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/**
* JDBC API 详解:Connection
*/
public class JDBCDemo3_Connection {
public static void main(String[] args) throws Exception {
//1. 注册驱动 建议写上去
Class.forName("com.mysql.jdbc.Driver");
//2. 获取连接,配置连接四要素
//jdbc:mysql://ip:数据库端口号/数据库名称?添加自定义参数
String url = "jdbc:mysql://127.0.0.1:3306/web22_day03_jdbc";
String username = "root";
String password = "root";
Connection conn = DriverManager.getConnection(url, username, password);
//3. 定义sql
String sql1 = "update account set money = money - 500 where id = 1";
String sql2 = "update account set money = money + 500 where id = 2";
//4. 获取执行sql的对象 Statement
Statement stmt = conn.createStatement();
try {
// 开启事务
conn.setAutoCommit(false);
//5. 执行sql
int count1 = stmt.executeUpdate(sql1);//受影响的行数
//6. 处理结果
System.out.println(count1);
int i = 3/0;
//5. 执行sql
int count2 = stmt.executeUpdate(sql2);//受影响的行数
//6. 处理结果
System.out.println(count2);
// 提交事务
conn.commit();
} catch (Exception throwables) {
// 回滚事务,手动开启事务之后,该操作可以省略。
// 没有没有提交,他也不会自动提交,就相当于回滚了。
// conn.rollback();
throwables.printStackTrace();
}
//7. 释放资源
stmt.close();
conn.close();
}
}
2.3 Statement
执行者对象,执行SQL
语句并返回SQL
语句执行的结果/结果集。
执行
DML/DDL
语句:修改(增删改)int executeUpdate(String sql);
返回值int:返回影响的行数。
参数sql:
insert
、update
、delete
语句。一般不会在
Java
代码中执行DDL
语句,Java
中主要完成对数据库中表记录的操作。执行
DQL
语句:查询ResultSet executeQuery(String sql);
返回值
ResultSet
:封装查询的结果集。参数
sql
:select
语句。释放资源
立即将执行者对象释放:
void close();
演示代码:演示增删改
/**
* statement执行dql,并获取结果集
* JDBC API 详解:Statement
*/
public class JDBCDemo4_Statement { /**
* 执行DML语句
* @throws Exception
*/
@Test
public void testDML() throws Exception {
//1. 注册驱动
//Class.forName("com.mysql.jdbc.Driver");
//2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写
String url = "jdbc:mysql:///maven?useSSL=false";
String username = "root";
String password = "root";
Connection conn = DriverManager.getConnection(url, username, password);
//3. 定义sql
String sql = "update account set money = 4000 where id = 1";
//4. 获取执行sql的对象 Statement
Statement stmt = conn.createStatement();
//5. 执行sql
int count = stmt.executeUpdate(sql);//执行完DML语句,受影响的行数 //6. 处理结果
if(count > 0){
System.out.println("修改成功~");
}else{
System.out.println("修改失败~");
}
//7. 释放资源
stmt.close();
conn.close(); } /**
* 执行DDL语句
* @throws Exception
*/
@Test
public void testDDL() throws Exception {
//1. 注册驱动
//Class.forName("com.mysql.jdbc.Driver");
//2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写
String url = "jdbc:mysql:///db1?useSSL=false";
String username = "root";
String password = "1234";
Connection conn = DriverManager.getConnection(url, username, password);
//3. 定义sql
String sql = "drop database db2";
//4. 获取执行sql的对象 Statement
Statement stmt = conn.createStatement();
//5. 执行sql
int count = stmt.executeUpdate(sql);//执行完DDL语句,可能是0
//6. 处理结果
//System.out.println(count);
/* if(count > 0){
System.out.println("修改成功~");
}else{ System.out.println("修改失败~");
}*/
System.out.println(count); //7. 释放资源
stmt.close();
conn.close(); }
}
演示代码:查询及结果集处理
public class JDBCDemo5_ResultSet { /**
* 执行DQL
*
* @throws Exception
*/
@Test
public void testResultSet() throws Exception {
//1. 注册驱动
//Class.forName("com.mysql.jdbc.Driver");
//2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写
String url = "jdbc:mysql:///maven?useSSL=false";
String username = "root";
String password = "root";
Connection conn = DriverManager.getConnection(url, username, password); //3. 定义sql
String sql = "select * from account"; //4. 获取statement对象
Statement stmt = conn.createStatement(); //5. 执行sql executeQuery
ResultSet rs = stmt.executeQuery(sql); // 6.1 光标向下移动一行,并且判断当前行是否有数据
while (rs.next()) { //移动到下一行
//6.2 获取数据 getXxx() int id = rs.getInt("id");
String name = rs.getString("name");
double money = rs.getDouble("money"); System.out.println("id = " + id);
System.out.println("name = " + name);
System.out.println("money = " + money);
} //7. 释放资源
rs.close();
stmt.close();
conn.close();
}
}
2.4 查询并封装POJO
对象案例
2.4.1 需求
查询account账户表数据,封装为Account对象中,并且存储到
ArrayList
集合中
2.4.2 核心步骤
- 使用上述操作完成查询,查询出结果集。
- 定义实体类
Account
- 查询数据,封装到
Account
对象中 - 将
Account
对象存入ArrayList
集合中
2.4.3 演示代码
package com.cy.pojo;
public class Account {
private int id;
private String name;
private double money;
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 double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", name='" + name + '\'' +
", money=" + money +
'}';
}
}
/**
* 实现需求:查询account账户表数据,封装为Account对象中,并且存储到ArrayList集合中
*/
public class JDBCDemo5_ResultSet {
/**
* 查询account账户表数据,封装为Account对象中,并且存储到ArrayList集合中
* 1. 定义实体类Account
* 2. 查询数据,封装到Account对象中
* 3. 将Account对象存入ArrayList集合中
*
*
* @throws Exception
*/
@Test
public void testResultSet2() throws Exception {
//1. 注册驱动
//Class.forName("com.mysql.jdbc.Driver");
//2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写
String url = "jdbc:mysql:///maven?useSSL=false";
String username = "root";
String password = "root";
Connection conn = DriverManager.getConnection(url, username, password);
//3. 定义sql
String sql = "select * from account";
//4. 获取statement对象 不能用(Statement)
//Statement stmt = conn.createStatement();
PreparedStatement pps = conn.prepareStatement(sql);
//5. 执行sql
//ResultSet rs = stmt.executeQuery(sql);
ResultSet rs = pps.executeQuery();
// 创建集合
List<Account> list = new ArrayList<>();
// 6.1 光标向下移动一行,并且判断当前行是否有数据
while (rs.next()){
Account account = new Account();
int id = rs.getInt("id");
String name = rs.getString("name");
double money = rs.getDouble("money1");
account.setId(id);
account.setName(name);
account.setMoney(money);
// 存入集合
list.add(account);
}
System.out.println(list);
//7. 释放资源
rs.close();
pps.close();
conn.close();
}
}
2.5 PreparedStatement
2.5.1概述
预编译的执行者对象,执行SQL
语句并返回SQL
语句执行的结果集。
相对于Statement
来说,PreparedStatement
有额外两个作用:
- 通过转义字符避免
SQL
注入问题。 - 开启预编译后,通过预编译可以提高
SQL
语句的执行效率。
2.5.2 使用及API
获取该对象
// 这里的SQL语句,不需要指定参数,而是通过?作为占位符,后面再通过setString方法把参数设置进来
PreparedStatement connection.prepareStatement(sql)
设置参数
// index 从1 开始
pst.setString(int index, String paramter)
执行
DML
语句:修改(增删改)int executeUpdate();
返回值int:返回影响的行数。
执行
DQL
语句:查询ResultSet executeQuery();
返回值
ResultSet
:封装查询的结果集。释放资源
立即将执行者对象释放:
void close();
演示代码
/**
*
* @throws Exception
*/
@Test
public void testPreparedStatement() throws Exception {
//2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写
String url = "jdbc:mysql:///db1?useSSL=false";
String username = "root";
String password = "1234";
Connection conn = DriverManager.getConnection(url, username, password); // 接收用户输入 用户名和密码
String name = "zhangsan";
String pwd = "' or '1' = '1"; // 定义sql 预编译sql ? 占位符
String sql = "select * from tb_user where username = ? and password = ?"; // 获取pstmt对象
PreparedStatement pstmt = conn.prepareStatement(sql); // 设置?的值
pstmt.setString(1,name);
pstmt.setString(2,pwd); // 执行sql
ResultSet rs = pstmt.executeQuery(); // 判断登录是否成功
if(rs.next()){
System.out.println("登录成功~");
}else{
System.out.println("登录失败~");
} //7. 释放资源
rs.close();
pstmt.close();
conn.close();
}
2.5.3 原理
可以通过日志看到其运行原理及效果。
准备工作1:开启预编译
想要看小预编译执行者对象的执行效果,需要先在
url
中开启预编译,添加如下自定义参数即可useServerPrepStmts=true
添加该参数后,完整的
URL
链接如下:jdbc:mysql:///db1?useSSL=false&useServerPrepStmts=true
准备工作2:打开日志,查看预编译等相关效果
在
my.ini
文件末尾,添加如下内容,并重启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
重启
MySQL
,方式1:可以打开服务窗口,手动重启
MySQL
服务。方式2:在以管理员身份打开的命令行中,键入以下命令
net stop mysql # 关闭mysql服务
net start mysql # 开启mysql服务
结论
通过修改查询相关代码,并查看日志,可以得出如下结论:
- 在
URL
中开启预编译后,相同模板的SQL
语句在创建预编译执行者对象的时候,就已经发送到SQL
,并完成了语法检查和编译。 - 预编译执行者对象,在往
SQL
模板中设置参数的时候,会对参数中的特殊符号添加转义字符\
,避免SQL
注入 - 使用相同模板的多条不同参数的
SQL
语句,只会在第一次创建预编译执行者对象的时候编译一次,从而提高执行效率。
- 在
演示代码
/**
* PreparedStatement原理
* @throws Exception
*/
@Test
public void testPreparedStatement2() throws Exception { //2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写
// useServerPrepStmts=true 参数开启预编译功能
String url = "jdbc:mysql:///db1?useSSL=false&useServerPrepStmts=true";
String username = "root";
String password = "root";
Connection conn = DriverManager.getConnection(url, username, password); // 接收用户输入 用户名和密码
String name = "zhangsan";
String pwd = "' or '1' = '1"; // 定义sql
String sql = "select * from tb_user where username = ? and password = ?"; // 获取pstmt对象
PreparedStatement pstmt = conn.prepareStatement(sql); Thread.sleep(10000);
// 设置?的值
pstmt.setString(1,name);
pstmt.setString(2,pwd);
ResultSet rs = null;
// 执行sql
rs = pstmt.executeQuery(); // 设置?的值
pstmt.setString(1,"aaa");
pstmt.setString(2,"bbb"); // 执行sql
rs = pstmt.executeQuery(); // 判断登录是否成功
if(rs.next()){
System.out.println("登录成功~");
}else{
System.out.println("登录失败~");
} //7. 释放资源
rs.close();
pstmt.close();
conn.close();
}
3. SQL注入及解决方案
3.1. 产生的原因
使用任意用户名并配合下面的密码,登录
' or '1' = '1
普通执行者对象拼接后的SQL
语句,变成了:
select * from tb_user where username = 'xxxx' and password = '' or '1' = '1'
普通的statement
只是把用户输入的用户名和密码进行了简单的拼接,拼接到了SQL
语句中。
这样,用户名或密码中特殊的单子或符号就被识别成了SQL
语句中的关键字或者是特殊符号。
思路:仅把' or 1=1 --
当做普通的字符串来处理,使用转义符号\
,然后面的符号表示其本来的意思(现原形)。
PreparedStatement
就是使用这个思路解决的。
PreparedStatement
中的方法public void setString(int parameterIndex, String x) throws SQLException
// 提前准备好长度变量,不用每次调用length()方法,效率高
int stringLength = x.length();
for(int i = 0; i < stringLength; ++i) {
// 获取参数的每一个字符
char c = x.charAt(i);
// 判断是否是特殊符号,如果是就在前面拼一个 \ 转义,让这个特殊符号表示自己原来的意思。
switch(c) {
case '\u0000':
buf.append('\\');
buf.append('0');
break;
case '\n':
buf.append('\\');
buf.append('n');
break;
case '\r':
buf.append('\\');
buf.append('r');
break;
case '\u001a':
buf.append('\\');
buf.append('Z');
break;
case '"':
if (this.usingAnsiMode) {
buf.append('\\');
}
buf.append('"');
break;
case '\'':
buf.append('\\');
buf.append('\'');
break;
case '\\':
buf.append('\\');
buf.append('\\');
break;
case '¥':
case '₩':
if (this.charsetEncoder != null) {
CharBuffer cbuf = CharBuffer.allocate(1);
ByteBuffer bbuf = ByteBuffer.allocate(1);
cbuf.put(c);
cbuf.position(0);
this.charsetEncoder.encode(cbuf, bbuf, true);
if (bbuf.get(0) == 92) {
buf.append('\\');
}
}
buf.append(c);
break;
default:
buf.append(c);
}
}
4. 连接池
4.1 概念
初始化并维护多个连接对象,当其他地方需要数据库连接时,从连接池获取;用完之后,归还到连接池。
以此实现连接的复用,提高效率。
数据源:DataSource
,内部维护了一个连接池,还提供了操作连接池的一些功能。
一般情况下,会把数据源和连接池混为一谈,把数据源喊做连接池。
常见的数据源有:C3P0
、Druid。我们学习Druid
。
4.2 池化思想(重要)
以空间换时间的做法。
游戏背包、新闻客户端。
- 提供更好的使用体验
- 对资源的消耗会更少。不会频繁的创建和销毁对象。
4.3 Druid
使用
4.3.1 导包
// 导包并添加到添加了模块类库
druid-1.1.12.jar
4.3.2 配置文件
properties
配置文件(名字任意),但是配置文件中key的值固定。常见参数如下:
# 连接四要素
# 数据库驱动全类名
driverClassName=com.mysql.jdbc.Driver
# URL
url=jdbc:mysql:///maven?useSSL=false&useServerPrepStmts=true
#用户名
username=root
#密码
password=root
# 其他参数
# 初始化连接数
initialSize=5
# 最大连接数
maxActive=10
# 超时时间
maxWait=3000
完整参数介绍:
属性 | 说明 | 建议值 |
---|---|---|
url | 数据库的jdbc连接地址。一般为连接oracle/mysql。示例如下: | |
mysql : jdbc:mysql://ip:port/dbname?option1&option2&… | ||
oracle : jdbc:oracle:thin:@ip:port:oracle_sid | ||
username | 登录数据库的用户名 | |
password | 登录数据库的用户密码 | |
initialSize | 启动程序时,在连接池中初始化多少个连接 | 10-50已足够 |
maxActive | 连接池中最多支持多少个活动会话 | |
maxWait | 程序向连接池中请求连接时,超过maxWait的值后,认为本次请求失败,即连接池 | 100 |
没有可用连接,单位毫秒,设置-1时表示无限等待 | ||
minEvictableIdleTimeMillis | 池中某个连接的空闲时长达到 N 毫秒后, 连接池在下次检查空闲连接时,将 | 见说明部分 |
回收该连接,要小于防火墙超时设置 | ||
net.netfilter.nf_conntrack_tcp_timeout_established的设置 | ||
timeBetweenEvictionRunsMillis | 检查空闲连接的频率,单位毫秒, 非正整数时表示不进行检查 | |
keepAlive | 程序没有close连接且空闲时长超过 minEvictableIdleTimeMillis,则会执 | true |
行validationQuery指定的SQL,以保证该程序连接不会池kill掉,其范围不超 | ||
过minIdle指定的连接个数。 | ||
minIdle | 回收空闲连接时,将保证至少有minIdle个连接. | 与initialSize相同 |
removeAbandoned | 要求程序从池中get到连接后, N 秒后必须close,否则druid 会强制回收该 | false,当发现程序有未 |
连接,不管该连接中是活动还是空闲, 以防止进程不会进行close而霸占连接。 | 正常close连接时设置为true | |
removeAbandonedTimeout | 设置druid 强制回收连接的时限,当程序从池中get到连接开始算起,超过此 | 应大于业务运行最长时间 |
值后,druid将强制回收该连接,单位秒。 | ||
logAbandoned | 当druid强制回收连接后,是否将stack trace 记录到日志中 | true |
testWhileIdle | 当程序请求连接,池在分配连接时,是否先检查该连接是否有效。(高效) | true |
validationQuery | 检查池中的连接是否仍可用的 SQL 语句,drui会连接到数据库执行该SQL, 如果 | |
正常返回,则表示连接可用,否则表示连接不可用 | ||
testOnBorrow | 程序 申请 连接时,进行连接有效性检查(低效,影响性能) | false |
testOnReturn | 程序 返还 连接时,进行连接有效性检查(低效,影响性能) | false |
poolPreparedStatements | 缓存通过以下两个方法发起的SQL: | true |
public PreparedStatement prepareStatement(String sql) | ||
public PreparedStatement prepareStatement(String sql, | ||
int resultSetType, int resultSetConcurrency) | ||
maxPoolPrepareStatement PerConnectionSize |
每个连接最多缓存多少个SQL | 20 |
filters | 这里配置的是插件,常用的插件有: | stat,wall,slf4j |
监控统计: filter:stat | ||
日志监控: filter:log4j 或者 slf4j | ||
防御SQL注入: filter:wall | ||
connectProperties | 连接属性。比如设置一些连接池统计方面的配置。 | |
druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 | ||
比如设置一些数据库连接属性: | ||
4.3.3 代码
public class DruidDemo {
public static void main(String[] args) throws Exception {
//1.导入jar包
//2.定义配置文件
//3. 加载配置文件 map集合 key-value
Properties prop = new Properties();
prop.load(new FileInputStream("web_day03_jdbc-demo/src/druid.properties"));
//4. 获取连接池对象
DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
//5. 获取数据库连接 Connection
Connection connection = dataSource.getConnection();
System.out.println(connection);
// 这里可以调用connection的close方法
// Druid充了connection的close方法,实现逻辑变成了回收连接,而非关闭连接
connection.close();
// 获取当前代码的运行路径,可以运行下面一行代码
//System.out.println(System.getProperty("user.dir"));
}
}
JavaWEB-03-JDBC的更多相关文章
- JavaWeb用Jdbc操作MySql数据库(一)
一.添加开发包.在JavaWeb中用jdbc操作数据库,使用方法与java一样,但是在处理开发包的问题上有点差别.JavaWeb不能将mysql-connector-java-5.1.7-bin.ja ...
- 【JavaWeb】JDBC连接MySQL数据库
正文之前 在之前写的JavaWeb项目中使用了JDBC,在此来回顾一下,并做个demo看看,先来看看JDBC的概念 Java数据库连接,(Java Database Connectivity,简称JD ...
- JavaWeb用Jdbc操作MySql数据库(二)
一.仍然使用前面的环境和示例数据库. 二.建立发出注册请求的页面index3.jsp. <%@ page language="java" import="java. ...
- JavaWeb之JDBC
一.介绍 C#定义了ADO.Net接口来实现对SQLServer.Oracel等数据库的访问,那Java定义了JDBC接口实现对数据库的访问,数据库提供商只要实现这些接口,Java语言就能访问数据库. ...
- JavaWeb 例子 JDBC+JSP登陆注册留言板
注册页面: <%@ page language="java" contentType="text/html; charset=UTF-8" pageEnc ...
- JavaWeb基础—JDBC(二)事务与批处理
一.批处理 这里给出PrepareStatement的示例,优点是可以发送预编译的SQL,缺点是SQL语句无法更换,但参数可以更换 批处理:多条语句的处理 mysql默认是关闭的,要打开需要在url后 ...
- JavaWeb基础—JDBC入门
一.什么是JDBC JDBC全称为:Java Data Base Connectivity(java数据库连接),它主要由接口组成 二.JDBC原理概述 JDBC原理:其实就是一组规范(就是对类的规范 ...
- Javaweb入门 JDBC第一天
JDBC的定义和作用 DBC(Java DataBase Connectivity) Java数据库连接, 其实就是利用Java语言/程序连接并访问数据库的一门技术. 之前我们可以通过cmd或者nav ...
- javaweb学习——JDBC(五)
管理结果集 JDBC使用ResultSet来封装查询到的结果集,然后移动记录指针来取出结果集的内容,除此之外,JDBC还允许通过ResultSet来更新记录,并提供了ResultSetMetaData ...
- javaweb 03: jsp
JSP 我的第一个JSP程序: 在WEB-INF目录之外创建一个index.jsp文件,然后这个文件中没有任何内容. 将上面的项目部署之后,启动服务器,打开浏览器,访问以下地址: http://loc ...
随机推荐
- 通过命令验证docker容器相当一个轻量级的Linux运行环境,且每个容器内都有一个属于自己的文件系统,容器之间相互隔离
一.docker的三个重要概念 1.镜像:打包项目带上环境,即镜像 Docker镜像是一个特殊的文件系统,除了提供容器运行时所需的程序.库.资源.配置等文件外,还包含了一些为运行时准备的配置参数.镜像 ...
- python实现基于smtp发送邮件
[前言] 在某些项目中,我们需要实现发送邮件的功能,比如: 爬虫结束后,发送邮件通知 定时发送邮件提醒待办事项 某项业务逻辑触发邮件通知 今天我们就分享如何基于smtp借助163邮箱来发送邮件 [实现 ...
- CSS展开收起
有一个问题是,在上述例子中,把段落内容的"浮动元素"去掉后,段落最后从"行"字开始换行了,"收起"却不换行,也就是会存在有两个字内容看不见情 ...
- Docker容器的数据卷
一.数据卷概念 1.数据卷是宿主机中的一个目录或文件 2.当容器目录和数据卷目录绑定后,对方的修改会立即同步 3.一个数据卷可以被多个容器同时挂载 4.一个容器也可以挂载多个数据卷 简单理解:有点类似 ...
- 一文彻底搞懂JavaScript中的prototype
prototype初步认识 在学习JavaScript中,遇到了prototype,经过一番了解,知道它是可以进行动态扩展的 function Func(){}; var func1 = new Fu ...
- Springcloud及Git线上配置详解
SpringCloud 这个阶段该如何学? 三层架构 + MVC 框架: Spring IOC AOP SpringBoot,新一代的JavaEE开发标准,自动装配 模块化~ all in one,代 ...
- zabbix 1.1
1.zabbix监控平台 2.zabbix的三部分组件: Zabbix server 是 Zabbix软件的核心组件,agent 向其报告可用性.系统完整性信息和统计信息.server也是存 ...
- 好客租房23-react组件的两种创建方式(抽离为独立js)
2.3抽离为单独组件 组件作为一个单独的个体,一般把每个组件放在单独的js中文件中 1创建hello.js 2在hello.js中导入React 3创建组件(函数或者类) hello.js子组件 // ...
- CF1682E Unordered Swaps
鸽着,我不知道为什么对? 题意: 思路: code: #include<bits/stdc++.h> using namespace std; const int N=5e5+5; int ...
- 第6章 字符串(下)——C++字符串
6.5 C++ strings(C++字符串) C风格字符串常见错误:试图去访问数组范围以外的元素:没有使用函数strcpy( )来实现字符串之间的复制:没有使用函数strcmp( )来比较两个字符串 ...