
- 一、JDBC概述
- 1.软件架构
- 2.数据的持久化
- 3. Java中的数据存储技术
- 4.JDBC介绍
- 5. JDBC体系结构
- 二、获取数据库连接
- 1.连接的方式
- 2.通用方式
- 3.Statement *** 作数据表的弊端
- 三、实现表数据的添加 *** 作
- 1.Java与SQL对应数据类型转换表
- 2.PreparedStatement的使用
- (1)实现增、删、改 *** 作
- (2)实现查询 *** 作
- 总结
一、JDBC概述 1.软件架构
- B/S:Browser Server(浏览器/服务器模式)
- C/S:Client Server(服务器/客户机)
把数据保存到可掉电式存储设备中以供之后使用
3. Java中的数据存储技术-
在Java中,数据库存取技术可分为如下几类:
-
JDBC直接访问数据库
-
JDO (Java Data Object )技术
-
第三方O/R工具,如Hibernate, Mybatis 等
-
-
JDBC是java访问数据库的基石,JDO、Hibernate、MyBatis等只是更好的封装了JDBC。
- JDBC(Java Database Connectivity)是一个独立于特定数据库管理系统、通用的SQL数据库存取和 *** 作的公共接口
- 面向应用的API:Java API,抽象接口,供应用程序开发人员使用(连接数据库,执行SQL语句,获得结果)。
- 面向数据库的API:Java Driver API,供开发商开发数据库驱动程序用。
JDBC是sun公司提供一套用于数据库 *** 作的接口,java程序员只需要面向这套接口编程即可。
不同的数据库厂商,需要针对这套接口,提供不同实现。不同的实现的集合,即为不同数据库的驱动。 ————面向接口编程
二、获取数据库连接 1.连接的方式代码如下(示例):
//方式一
@Test
public void testConnection1() throws SQLException {
Driver driver = new com.mysql.jdbc.Driver();
// url:http://localhost:8080/gmall/keyboard.jpg
// jdbc:mysql:协议
// localhost:ip地址
// 3306:默认mysql的端口号
// test:test数据库
String url="jdbc:mysql://localhost:3306/test";
// 将用户名和密码封装在Properties中
Properties info=new Properties();
info.setProperty("user","root");
info.setProperty("password","123456");
Connection conn = driver.connect(url, info);
System.out.println(conn);
}
//方式二
//在如下的程序中不出现第三方的api,使得程序具有更好的移植性
@Test
public void testConnection2() throws Exception {
//获取Driver实现类的对象:使用反射
Class clazz = Class.forName("com.mysql.jdbc.Driver");
Driver driver = (Driver) clazz.newInstance();
//提供要连接的数据库
String url="jdbc:mysql://localhost:3306/test";
Properties info=new Properties();
info.setProperty("user","root");
info.setProperty("password","123456");
Connection conn = driver.connect(url, info);
System.out.println(conn);
}
//方式三
// 方式三:使用DriverManager替换Driver
@Test
public void testConnection3() throws Exception{
//获取Driver实现类的对象:使用反射
Class clazz = Class.forName("com.mysql.jdbc.Driver");
Driver driver = (Driver) clazz.newInstance();
//注册驱动
DriverManager.registerDriver(driver);
String url="jdbc:mysql://localhost:3306/test";
String user="root";
String password = "123456";
Connection conn = DriverManager.getConnection(url,user,password);
System.out.println(conn);
}
//方式四
@Test
public void testConnection4() throws Exception {
// 1.提供三个连接的基本信息:
String url = "jdbc:mysql://localhost:3306/test";
String user = "root";
String password = "abc123";
// 2.加载Driver
Class.forName("com.mysql.jdbc.Driver");//这个也可以省略,但是最好不要省略,因为只有mysql好使,其他不行
//相较于方式三,可以省略如下的 *** 作:
// Driver driver = (Driver) clazz.newInstance();
// // 注册驱动
// DriverManager.registerDriver(driver);
//为什么可以省略上述 *** 作呢?
// 3.获取连接
Connection conn = DriverManager.getConnection(url, user, password);
System.out.println(conn);
}
2.通用方式
代码如下(示例):
//方式五(final版):将数据库连接需要的4个基本信息声明在配置文件中,通过读取配置文件的方式,获取连接
@Test
public void getConnection5() throws Exception{
//1.读取配置文件中的4个基本信息
InputStream is = ConnectionTest.class.getClassLoader().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);
System.out.println(conn);
}
3.Statement *** 作数据表的弊端
- 问题一:存在拼串 *** 作,繁琐
- 问题二:存在SQL注入问题
- SQL 注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的 SQL 语句段或命令:(如:SELECt user, password FROM user_table WHERe user=‘a’ OR 1 = ’ AND password = ’ OR ‘1’ = ‘1’) ,从而利用系统的 SQL 引擎完成恶意行为的做法。
通用:
@Test
public void testCommonUpdate(){
// String sql = "delete from customers where id = ?";
// update(sql,3);
String sql = "update `order` set order_name = ? where order_id = ?";
update(sql,"DD","2");
}
//通用的增删改 *** 作
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);
}
}
(2)实现查询 *** 作
针对于表的字段名与类的属性名不相同的情况:
- 必须声明sql时,使用类的属性名来命名字段的别名
- 使用ResultSetmetaData时,需要使用getColumnLabel()来替换getColumnName(), 获取列的别名。
说明:如果sql中没有给字段其别名,getColumnLabel()获取的就是列名
工具类
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
// *** 作数据库的工具类
public class JDBCUtils {
//获取数据库的连接
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;
}
//关闭连接和Statement的 *** 作
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();
}
}
}
通用(单行数据):
@Test
public void testGetInstance(){
String sql = "select id,name,email from customers where id = ?";
Customer customer = getInstance(Customer.class,sql,12);
System.out.println(customer);
String sql1 = "select order_id orderId,order_name orderName from `order` where order_id = ?";
Order order = getInstance(Order.class, sql1, 1);
System.out.println(order);
}
//针对于不同的表的通用的查询 *** 作,返回表中的一条记录
public T getInstance(Class 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;
}
通用(多行数据):
@Test
public void testGetForList(){
String sql = "select id,name,email from customers where id < ?";
List list = getForList(Customer.class,sql,12);
list.forEach(System.out::println);
String sql1 = "select order_id orderId,order_name orderName from `order`";
List orderList = getForList(Order.class, sql1);
orderList.forEach(System.out::println);
}
public List getForList(Class 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();
//创建集合对象
ArrayList list = new ArrayList();
while (rs.next()) {
T t = clazz.newInstance();
// 处理结果集一行数据中的每一个列:给t对象指定的属性赋值
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);
}
list.add(t);
}
return list;
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.closeResource(conn, ps, rs);
}
return null;
}
总结
ORM编程思想:
- 一个数据表对应一个java类
- 表中的一条记录对应java类的一个对象
- 表中的一个字段对应java类的一个属性
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)