目录
三,CRUD操作(create(增加),read(查),update(修改),delete(删除))步骤
1)导入jar包(丰富的工具类)加载JDBC驱动程序,并获取连接
2) 预编译sql语句,返回PrepareStatement的实例对象
一,前言
1.数据的持续化:把数据保存到可掉电式存储设备中以供之后使用。
大多数情况下,特别是企业级应用,数据持久化意味着将内存中的数据保存到硬盘上加以”固化”,
而持久化的实现过程大多通过各种关系数据库来完成。
2.四个操作增删改操作步骤是相同的,但是查询操作略有不同,需要创建一个对象对其查询的结果集进行存放(也是需要重点理解的一步)。
3.java中的数据存储技术:
JDBC,JDO(Java Data Object),第三方O/R工具,如Hibernate、Mybatis等。
JDBC是java访问数据库的基石,JDO、Hibernate、MyBatis等只是更好的封装了JDBC
4.需要掌握两种思想以及两种技术
面向接口编程的思想
ORM思想(object relational mapping):
一个数据表对应一个java类
表中的一条记录对应java类的一个对象
表中的一个字段对应java类的一个属性
注意:sql是需要结合列名和表的属性名来写。注意起别名。
JDBC结果集的元数据:ResultSetMetaData:
获取列数:getColumnCount()
获取列的别名:getColumnLabel()
通过反射,创建指定类的对象,获取指定的属性并赋值
二,JDBC(了解)
概述:
JDBC(Java DataBase Connectivity)是Java和数据库之间的一个桥梁,是一个规范而不是一个实现,能够执行SQL语句。它由一组用Java语言编写的类和接口组成。各种不同类型的数据库都有相应的实现。
三,CRUD操作(create(增加),read(查),update(修改),delete(删除))步骤
主要说一下查询操作(也就包含了增删改操作)
1)导入jar包(丰富的工具类)加载JDBC驱动程序,并获取连接
创建lib包将jar导入
jar包添加到依赖中
将四个基本信息写入到配置文件当中并通过Properties集合读取配置文件获取信息
四个基本信息为:
(1)user用户名
(2)password密码
(3)URL定义了连接数据库时的协议、子协议、数据源标识
(4)driverClass连接数据库所需的驱动。
//配置文件
user=root
password=root
url=jdbc:mysql://localhost:3306/test
driverClass=com.mysql.jdbc.Driver
//获取数据库连接
public static Connection getConnection() throws Exception {
// 1.读取配置文件中的4个基本信息
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
Properties pros = new Properties();
pros.load(is);
String user = pros.getProperty("user");
String password = pros.getProperty("password");
String url = pros.getProperty("url");
String driverClass = pros.getProperty("driverClass");
// 2.加载驱动
Class.forName(driverClass);
// 3.获取连接
Connection conn = DriverManager.getConnection(url, user, password);
return conn;
}
2) 预编译sql语句,返回PrepareStatement的实例对象
要执行SQL语句,必须获得java.sql.Statement实例,Statement实例分为以下3 种类型:
(1)执行静态SQL语句。通常通过Statement实例实现。
(.存在sql注入问题(列名与关键字混淆))
(2)执行动态SQL语句。通常通过PreparedStatement实例实现。
(推荐使用,解决statement的问题)
(3)执行数据库存储过程。通常通过CallableStatement实例实现。
//2.预编译sql语句,返回PreparedStatement的实例
PreparedStatement ps = conn.prepareStatement(sql);
4)执行sql语句
除了查询语句是executeQuery();其他全部是executeUpdate();
ResultSet rs = ps.executeQuery();
Statement接口下的方法:
boolean execute(String sql)----执行SQL语句,如果返回值是结果集则为true,否则为false
ResultSet executeQuery(String sql)----执行SQL语句,返回值为ResultSet
int executeUpdate(String sql)----执行SQL语句,返回值为所影响的行数
5)获取并处理结果集
ResultSet对象的getXxxx方法,取决于数据库中表的字段的类型,例如:varchar2 对应方法是getString ,如果是 integer 对应方法是getInt/getLong
// 获取结果集的元数据 :ResultSetMetaData
ResultSetMetaData rsmd = rs.getMetaData();
// 通过ResultSetMetaData获取结果集中的列数
int columnCount = rsmd.getColumnCount();
if (rs.next()) {
T t = clazz.newInstance();
// 处理结果集一行数据中的每一个列
for (int i = 0; i < columnCount; i++) {
// 获取列值
Object columValue = rs.getObject(i + 1);
// 获取每个列的列名
// String columnName = rsmd.getColumnName(i + 1);
String columnLabel = rsmd.getColumnLabel(i + 1);
// 给t对象指定的columnName属性,赋值为columValue:通过反射
Field field = clazz.getDeclaredField(columnLabel);
field.setAccessible(true);
field.set(t, columValue);
}
return t;
}
6)资源的释放(close()
- 释放ResultSet, Statement,Connection。
- 数据库连接(Connection)是非常稀有的资源,用完后必须马上释放,如果Connection不能及时正确的关闭将导致系统宕机。Connection的使用原则是尽量晚创建,尽量早的释放。
- 可以在finally中关闭,保证及时其他代码出现异常,资源也一定能被关闭。
//关闭资源
//增删改操作
public static void closeResource(Connection conn, Statement ps){
try {
if(ps != null)
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
//查询操作,也就多了一个需要关闭的获取的结果集
public static void closeResource(Connection conn, Statement ps, ResultSet rs){
try {
if(ps != null)
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(rs != null)
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
通用形式代码:
import java.io.InputStream;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.Properties;
/**
*
* @Description 操作数据库的工具类
* @author shkstart Email:shkstart@126.com
* @version
* @date 上午9:10:02
*
*/
public class JDBCUtils {
/**
*
* @Description 获取数据库的连接
* @author shkstart
* @date 上午9:11:23
* @return
* @throws Exception
*/
public static Connection getConnection() throws Exception {
// 1.读取配置文件中的4个基本信息
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
Properties pros = new Properties();
pros.load(is);
String user = pros.getProperty("user");
String password = pros.getProperty("password");
String url = pros.getProperty("url");
String driverClass = pros.getProperty("driverClass");
// 2.加载驱动
Class.forName(driverClass);
// 3.获取连接
Connection conn = DriverManager.getConnection(url, user, password);
return conn;
}
/**
*
* @Description 关闭连接和Statement的操作
* @author shkstart
* @date 上午9:12:40
* @param conn
* @param ps
*/
public static void closeResource(Connection conn, Statement ps){
try {
if(ps != null)
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
*
* @Description 关闭资源操作
* @author shkstart
* @date 上午10:21:15
* @param conn
* @param ps
* @param rs
*/
public static void closeResource(Connection conn, Statement ps, ResultSet rs){
try {
if(ps != null)
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(rs != null)
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
//通用的增删改操作
public void update(String sql,Object ...args){//sql中占位符的个数与可变形参的长度相同!
Connection conn = null;
PreparedStatement ps = null;
try {
//1.获取数据库的连接
conn = JDBCUtils.getConnection();
//2.预编译sql语句,返回PreparedStatement的实例
ps = conn.prepareStatement(sql);
//3.填充占位符
for(int i = 0;i < args.length;i++){
ps.setObject(i + 1, args[i]);//小心参数声明错误!!
}
//4.执行
ps.execute();
} catch (Exception e) {
e.printStackTrace();
}finally{
//5.资源的关闭
JDBCUtils.closeResource(conn, ps);
}
}
//通用的对不同表进行查询
public static <T> T getInstance(Class<T> clazz, String sql, Object... args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JDBCUtils.getConnection();
ps = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
rs = ps.executeQuery();
// 获取结果集的元数据 :ResultSetMetaData
ResultSetMetaData rsmd = rs.getMetaData();
// 通过ResultSetMetaData获取结果集中的列数
int columnCount = rsmd.getColumnCount();
if (rs.next()) {
T t = clazz.newInstance();
// 处理结果集一行数据中的每一个列
for (int i = 0; i < columnCount; i++) {
// 获取列值
Object columValue = rs.getObject(i + 1);
// 获取每个列的列名
// String columnName = rsmd.getColumnName(i + 1);
String columnLabel = rsmd.getColumnLabel(i + 1);
// 给t对象指定的columnName属性,赋值为columValue:通过反射
Field field = clazz.getDeclaredField(columnLabel);
field.setAccessible(true);
field.set(t, columValue);
}
return t;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.closeResource(conn, ps, rs);
}
return null;
}
}