内容

  • JDBC `JDBC`简介
  • JDBC `JDBC`快速入门
  • JDBC API `JDBC API` 详解
  • 数据库连接池
  • JDBC `JDBC`案例

1. JDBC入门

1.1 概述

  • 概念

    JDBC:Java DataBase ConnectivityJava数据库连接

    JDBC就是使用Java语言操作关系型数据库的一套API

    Sun公司和数据库厂商共同制定的一套连接并操作数据库的统一规范(接口),由数据库厂商负责实现(驱动Jar包);我们使用的时候只需要导入数据库厂商已经实现好的jar包即可。

  • 好处

    因为各个数据库厂商都实现了同一套JDBC接口规范。

    1. 我们可以使用同一套Java代码操作不同的关系型数据库
    2. 访问数据库的Java代码不改变的前提下,替换不同的驱动Jar包可以轻松更换数据库
  • 我们要怎么做

    整体思路:基于JDBC定义的规则编码,不用考虑不同数据库之间的差异

    1. 导数对应据库驱动包。
    2. 基于JDBC定义的规则轻松编程。

1.2 quick start

  • 实现步骤

    1. 导入Jar
    2. 注册驱动
    3. 获取连接
    4. 获取执行者对象
    5. 执行SQL语句,并且接收结果
    6. 处理结果
    7. 释放资源
  • 演示代码

    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:注册驱动

  • 不需要手动调用DriverManagerAPI注册,而是保证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:返回影响的行数。

    参数sqlinsertupdatedelete语句。

    一般不会在Java代码中执行DDL语句,Java中主要完成对数据库中表记录的操作。

  • 执行DQL语句:查询

    ResultSet executeQuery(String sql);

    返回值ResultSet:封装查询的结果集。

    参数sqlselect语句。

  • 释放资源

    立即将执行者对象释放: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 核心步骤

  1. 使用上述操作完成查询,查询出结果集。
  2. 定义实体类Account
  3. 查询数据,封装到Account对象中
  4. 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有额外两个作用:

  1. 通过转义字符避免SQL注入问题。
  2. 开启预编译后,通过预编译可以提高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服务
  • 结论

    通过修改查询相关代码,并查看日志,可以得出如下结论:

    1. URL中开启预编译后,相同模板的SQL语句在创建预编译执行者对象的时候,就已经发送到SQL,并完成了语法检查和编译。
    2. 预编译执行者对象,在往SQL模板中设置参数的时候,会对参数中的特殊符号添加转义字符\,避免SQL注入
    3. 使用相同模板的多条不同参数的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 池化思想(重要)

以空间换时间的做法。

游戏背包、新闻客户端。

  1. 提供更好的使用体验
  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的更多相关文章

  1. JavaWeb用Jdbc操作MySql数据库(一)

    一.添加开发包.在JavaWeb中用jdbc操作数据库,使用方法与java一样,但是在处理开发包的问题上有点差别.JavaWeb不能将mysql-connector-java-5.1.7-bin.ja ...

  2. 【JavaWeb】JDBC连接MySQL数据库

    正文之前 在之前写的JavaWeb项目中使用了JDBC,在此来回顾一下,并做个demo看看,先来看看JDBC的概念 Java数据库连接,(Java Database Connectivity,简称JD ...

  3. JavaWeb用Jdbc操作MySql数据库(二)

    一.仍然使用前面的环境和示例数据库. 二.建立发出注册请求的页面index3.jsp. <%@ page language="java" import="java. ...

  4. JavaWeb之JDBC

    一.介绍 C#定义了ADO.Net接口来实现对SQLServer.Oracel等数据库的访问,那Java定义了JDBC接口实现对数据库的访问,数据库提供商只要实现这些接口,Java语言就能访问数据库. ...

  5. JavaWeb 例子 JDBC+JSP登陆注册留言板

    注册页面: <%@ page language="java" contentType="text/html; charset=UTF-8" pageEnc ...

  6. JavaWeb基础—JDBC(二)事务与批处理

    一.批处理 这里给出PrepareStatement的示例,优点是可以发送预编译的SQL,缺点是SQL语句无法更换,但参数可以更换 批处理:多条语句的处理 mysql默认是关闭的,要打开需要在url后 ...

  7. JavaWeb基础—JDBC入门

    一.什么是JDBC JDBC全称为:Java Data Base Connectivity(java数据库连接),它主要由接口组成 二.JDBC原理概述 JDBC原理:其实就是一组规范(就是对类的规范 ...

  8. Javaweb入门 JDBC第一天

    JDBC的定义和作用 DBC(Java DataBase Connectivity) Java数据库连接, 其实就是利用Java语言/程序连接并访问数据库的一门技术. 之前我们可以通过cmd或者nav ...

  9. javaweb学习——JDBC(五)

    管理结果集 JDBC使用ResultSet来封装查询到的结果集,然后移动记录指针来取出结果集的内容,除此之外,JDBC还允许通过ResultSet来更新记录,并提供了ResultSetMetaData ...

  10. javaweb 03: jsp

    JSP 我的第一个JSP程序: 在WEB-INF目录之外创建一个index.jsp文件,然后这个文件中没有任何内容. 将上面的项目部署之后,启动服务器,打开浏览器,访问以下地址: http://loc ...

随机推荐

  1. Linux中的RCU机制

    什么是RCU? RCU(Read-Copy Update),顾名思义就是读-拷贝-修改,它是基于其原理命名的.对于被RCU保护的共享数据结构,读者不需要获得任何锁就可以访问它,但写者在访问它时首先拷贝 ...

  2. Go语言学习——map

    map 映射关系容器 内部使用散列表(hash)实现 map是引用类型 必须初始化才能使用 无序的基于key-value的数据结构 map定义 map的定义语法: map[KeyType]ValueT ...

  3. 入行IT,一定要会Linux吗?

    现在是21世纪,是科学技术大力发展的一个时代,IT行业已经成为现在的一个非常热门的一个行业,许许多多的人都想要往IT方面发展,找IT方面相关的一个工作.很多想要接触IT行业的初学者伤透了脑筋,我该学什 ...

  4. 简单易懂的 Go 泛型使用和实现原理介绍

    原文:A gentle introduction to generics in Go by Dominik Braun 万俊峰Kevin:我看了觉得文章非常简单易懂,就征求了作者同意,翻译出来给大家分 ...

  5. JavaScript 任务池

    JavaScript 任务池 本文写于 2022 年 5 月 13 日 线程池 在多线程语言中,我们通常不会随意的在需要启动线程的时候去启动,而是会选择创建一个线程池. 所谓线程池,本意其实就是(不止 ...

  6. idea maven 依赖还原不上的问题 method <init>()V not found

    问题 还原项目依赖的时候报错: java.lang.RuntimeException: org.codehaus.plexus.component.repository.exception.Compo ...

  7. 一起看 I/O | Flutter 休闲游戏工具包发布

    作者 / Zoey Fan, Product Manager for Flutter, Google 对于大多数开发者来说,Flutter 是一个应用框架.但利用 Flutter 提供的硬件加速图形支 ...

  8. 好客租房10-jsx的基本使用

    1.1createElement()的问题 1繁琐不简洁 2不直观 无法一眼看出所描述的结构 3不优雅 用户体验不爽 React.createElement("div",     ...

  9. 广义SAM

    参考 还有首先你要会SAM吧~ 用途 相比与单串SAM,广义自动机能存储的是多个字符串. 有两种写法,第一种是离线利用trie树结构,第二种是在线伪广义SAM 离线+Trie 首先构建出trie树. ...

  10. JAVA - 线程从创建到死亡的几种状态都有哪些?

    JAVA - 线程从创建到死亡的几种状态都有哪些? 新建( new ):新创建了一个线程对象. 可运行( runnable ):线程对象创建后,其他线程(比如 main 线程)调用了该对象 的 sta ...