概述
jdbc是javaWeb的技术框架
定义
JDBC(Java Database Connectivity)是一个独立于特定数据库管理系统、通用的SQL数据库存取和操作的公共接口(一组API),定义了用来访问数据库的标准Java类库,(java.sql,javax.sql)使用这些类库可以以一种标准的方法、方便地访问数据库资源。
作用
JDBC的目标是使Java程序员使用JDBC可以连接任何提供了JDBC驱动程序的数据库系统,这样就使得程序员无需对特定的数据库系统的特点有过多的了解,从而大大简化和加快了开发过程。
图片示例:
系统结构
JDBC接口(API)包括两个层次:
面向应用的API:Java API,抽象接口,供应用程序开发人员使用(连接数据库,执行SQL语句,获得结果)。
面向数据库的API:Java Driver API,供开发商开发数据库驱动程序用。
JDBC是sun公司提供一套用于数据库操作的接口,java程序员只需要面向这套接口编程即可。
不同的数据库厂商,需要针对这套接口,提供不同实现。不同的实现的集合,即为不同数据库的驱动。 ————面向接口编程
JDBC步骤
图示:
导入jar包 添加到当前类库中
加载注册驱动 Driver的实现类
获取数据库连接对象Connection
创建执行sql的对象
执行sql DML增删改 DQL查询
如果是增删改拿到影响行数的返回结果 ,如果是查询就获取ResultSet对象
关闭资源 ResultSet Connection
连接三要素
要素1 Driver驱动
Driver接口
java.sql.Driver 接口是所有 JDBC 驱动程序需要实现的接口。这个接口是提供给数据库厂商使用的,不同数据库厂商提供不同的实现。在程序中不需要直接去访问实现了 Driver 接口的类,而是由驱动程序管理器类(java.sql.DriverManager)去调用这些Driver实现。
加载与注册JDBC驱动
加载驱动:加载 JDBC 驱动需调用 Class 类的静态方法 forName(),向其传递要加载的 JDBC 驱动的类名
Class.forName(“com.mysql.cj.jdbc.Driver”);
注册驱动:DriverManager 类是驱动程序管理器类,负责管理驱动程序:
使用DriverManager.registerDriver(com.mysql.jdbc.Driver)来注册驱动
(通常不需要注册)
要素2 url
JDBC URL 用于标识一个被注册的驱动程序,驱动程序管理器通过这个 URL 选择正确的驱动程序,从而建立到数据库的连接。
JDBC URL的标准由三部分组成,各部分间用冒号分隔。 http://
jdbc:子协议:子名称
协议:JDBC URL中的协议总是jdbc
子协议:子协议用于标识一个数据库驱动程序
子名称:一种标识数据库的方法。子名称可以依不同的子协议而变化,用子名称的目的是为了定位数据库提供足够的信息。包含主机名(对应服务端的ip地址),端口号,数据库名
jdcb主协议
mysql子协议
localhost:3306 本机的mysql
java2312 要操作的数据库
jdbc:mysql://localhost:3306/java2312
要素三 用户名和密码
user,password可以用“属性名=属性值”方式告诉数据库
可以调用 DriverManager 类的 getConnection() 方法建立到数据库的连接
连接方式
连接方式1
public void conOne() throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException {
//连接方式1
// driver全类名 要素1
String driveClass = "com.mysql.cj.jdbc.Driver";
// url 连接路径 要素2
String url = "jdbc:mysql://localhost:3306/java2312";
// 用户名 密码 要素3
String user= "root";
String password = "121812";
// 实例化driver
Class<?> aClass = Class.forName(driveClass);
Driver driver = (Driver) aClass.newInstance();
// 注册驱动 可选
DriverManager.registerDriver(driver);
// 获取连接
Connection connection = DriverManager.getConnection(url, user, password);
System.out.println(connection);
}
连接方式2
jdbc.properties
driverClass=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/java2312
username=root
password=111111
java代码
/*
将 三大要素 存放到 配置文件中
文件名一般都叫jdbc.properties
内容以key = value的形式编写
再通过io的形式读取出来
*/
// 如果test测试单元 根目录实在模块下 如果main方法是在项目下
FileInputStream fileInputStream = new FileInputStream("jdbc.properties");
// 用来读取配置文件
Properties properties = new Properties();
properties.load(fileInputStream);
// 驱动
String driverClass = properties.getProperty("driverClass");
//url
String url = properties.getProperty("url");
//用户名
String username = properties.getProperty("username");
//密码
String password = properties.getProperty("password");
// 加载驱动
Class.forName(driverClass);
//获取连接
Connection connection = DriverManager.getConnection(url, username, password);
System.out.println(connection);
执行DML语句
Connection connection = null;
try {
//获取连接对象
connection = ConnectionUtil.getConnection();
// 获取sql执行对象
Statement statement = connection.createStatement();
String sql ="delete from account where id in(1,2);";
int i = statement.executeUpdate(sql);
System.out.println(i);
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
//关闭资源
ConnectionUtil.close(connection);
}
sql注入问题
SQL 注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的 SQL 语句段或命令(如:SELECT user, password FROM user_table WHERE user='a' OR 1 = ' AND password = ' OR '1' = '1') ,从而利用系统的 SQL 引擎完成恶意行为的做法。
preparedStatement
可以通过调用 Connection 对象的 preparedStatement(String sql) 方法获取 PreparedStatement 对象
PreparedStatement 接口是 Statement 的子接口,它表示一条预编译过的 SQL 语句
PreparedStatement 对象所代表的 SQL 语句中的参数用问号(?)来表示,调用 PreparedStatement 对象的 setXxx() 方法来设置这些参数. setXxx() 方法有两个参数,第一个参数是要设置的 SQL 语句中的参数的索引(从 1 开始),第二个是设置的 SQL 语句中的参数的值
@Test
public void preparedStatementTest1() {
Connection connection = null;
ResultSet resultSet = null;
try {
connection = ConnectionUtil.getConnection();
//查询sql ?是占位符
String sql="select * from user_table where user_name=? and password =?;";
// 获取 对象 传入一个预编译sql
PreparedStatement ps = connection.prepareStatement(sql);
// 设置占位符内容
// 第几个占位符从1开始,占位符内容
ps.setString(1,"1'or");
ps.setString(2,"=1 or '1'='1");
// 执行查询语法
resultSet = ps.executeQuery();
if (resultSet.next()){
System.out.println("登录成功");
}else {
System.out.println("登录失败");
}
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
//关闭资源
ConnectionUtil.close(connection,resultSet);
}
}
preparedStatement和Statement区别
statement不对sql语句做处理,直接交给数据库;而prepraedstatement是支持预编译的,会将编译好的sql语句放在数据库端,相当于缓存,对于多次重复执行的sql语句,使用prepraedstatement可以使得代码的执行效率更高。
java对应sql的数据类型表
封装公共的增加修改删除
/**
* 公用的增加 修改 删除的方法
* @param sql 预编译sql
* @param args 占位符的内容
* @return
*/
public static int publicUpdate(String sql,Object ... args) {
Connection connection = null;
int num = 0;
try {
//1获取连接对象
connection = ConnectionUtil.getConnection();
//2获取操作sql的对象
PreparedStatement ps = connection.prepareStatement(sql);
//3充填占位符
for (int i = 0; i < args.length; i++) {
ps.setObject(i+1,args[i]);
}
//4执行sql
num = ps.executeUpdate();
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
//5关闭资源
ConnectionUtil.close(connection);
}
return num;
}
ResultSet
@Test
public void test1() throws SQLException {
Connection connection = ConnectionUtil.getConnection();
String sql = "select * from account";
PreparedStatement ps = connection.prepareStatement(sql);
ResultSet resultSet = ps.executeQuery();
// next 查看是否有下一条记录
// System.out.println(resultSet.next());
// System.out.println(resultSet.next());
// System.out.println(resultSet.next());
// getXxx :getObject getString
/*
通过列数或者字段名别名来拿到当前单元格中的信息
*/
while (resultSet.next()){
int id = resultSet.getInt("id");
String userName = resultSet.getString("user_name");
double money = resultSet.getDouble("money");
//将查询出来的数据 转换为javaBean对象
AccountBean accountBean = new AccountBean(id, userName, money);
System.out.println(accountBean);
}
}
MetaData
通过metaData获取内容 :
while (resultSet.next()){
ResultSetMetaData metaData = resultSet.getMetaData();
// 返回当前查询结果中的列的个数
int columnCount = metaData.getColumnCount();
//根据列数进行循环
for (int i = 0; i < columnCount; i++) {
//获取当前列的别名 如果没有起别名 那么默认获取的就是列名
String key = metaData.getColumnLabel(i+1);
//通过resultSet 根据别名获取值
Object value = resultSet.getObject(key);
System.out.println(key+":"+value);
}
// 获取当前列的列名
// String columnName = metaData.getColumnName(1);
封装查询
/**
* 查询 单个对象
* @param clazz 对象的类型
* @param sql 预编译sql
* @param args 占位符内容
* @return 对应的对象
* @param <T>
* @throws Exception
*/
public static <T> T querySingle(Class<T> clazz, String sql, Object... args) {
Connection connection = null;
ResultSet resultSet = null;
T o = null;
try {
connection = ConnectionUtil.getConnection();
PreparedStatement ps = connection.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
resultSet = ps.executeQuery();
o = null;
if (resultSet.next()) {
o= clazz.newInstance();
ResultSetMetaData metaData = resultSet.getMetaData();
// 返回当前查询结果中的列的个数
int columnCount = metaData.getColumnCount();
//根据列数进行循环
for (int i = 0; i < columnCount; i++) {
//获取当前列的别名 如果没有起别名 那么默认获取的就是列名
String key = metaData.getColumnLabel(i + 1);
//通过resultSet 根据别名获取值
Object value = resultSet.getObject(key);
// 获取类的属性对象
Field declaredField = clazz.getDeclaredField(key);
// 暴力破解 能够操作private修饰的属性
declaredField.setAccessible(true);
declaredField.set(o,value);
}
}
} catch (SQLException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
} finally {
//关流
ConnectionUtil.close(connection,resultSet);
}
return o;
}
/**
* 查询多列数据
* @param clazz
* @param sql
* @param args
* @return
* @param <T>
*/
public static <T> List<T> queryList(Class<T> clazz, String sql, Object... args) {
Connection connection = null;
ResultSet resultSet = null;
T o = null;
ArrayList<T> list = new ArrayList<>();
try {
connection = ConnectionUtil.getConnection();
PreparedStatement ps = connection.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
resultSet = ps.executeQuery();
o = null;
while (resultSet.next()) {
o= clazz.newInstance();
ResultSetMetaData metaData = resultSet.getMetaData();
// 返回当前查询结果中的列的个数
int columnCount = metaData.getColumnCount();
//根据列数进行循环
for (int i = 0; i < columnCount; i++) {
//获取当前列的别名 如果没有起别名 那么默认获取的就是列名
String key = metaData.getColumnLabel(i + 1);
//通过resultSet 根据别名获取值
Object value = resultSet.getObject(key);
// 获取类的属性对象
Field declaredField = clazz.getDeclaredField(key);
// 暴力破解 能够操作private修饰的属性
declaredField.setAccessible(true);
declaredField.set(o,value);
}
//将对象放入list集合中
list.add(o);
}
} catch (SQLException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
} finally {
//关流
ConnectionUtil.close(connection,resultSet);
}
return list;
}
标签:JDBC,String,数据库,resultSet,connection,sql,new,JavaWeb
From: https://blog.csdn.net/rxdasd123456/article/details/140109083