目录
前面我们讲到了sql的学习已经慢慢的结束,结果马上JDBC里面就见到了我们的老朋友哈哈,今天为大家带来了JDBC的学习!
初识JDBC,感觉很熟悉但是其实又很陌生哈哈,这就是第一感觉
JDBC概述
1.1 数据的持久化
1. 持久化(persistence):把数据保存到可掉电式存储设备中以供之后使用。大多数情况下,特别是企业级应用,数据持久化意味着将内存中的数据保存到硬盘上加以”固化”,而持久化的实现过程大多通过各种关系数据库来完成。
2. 持久化的主要应用是将内存中的数据存储在关系型数据库中,当然也可以存储在磁盘文件、XML数据文件中。
1.2 Java中的数据存储技术
-
在Java中,数据库存取技术可分为如下几类:
-
JDBC直接访问数据库
-
JDO (Java Data Object )技术
-
第三方O/R工具,如Hibernate, Mybatis 等
-
-
JDBC是java访问数据库的基石,JDO、Hibernate、MyBatis等只是更好的封装了JDBC。
1.3 JDBC介绍
-
JDBC(Java Database Connectivity)是一个独立于特定数据库管理系统、通用的SQL数据库存取和操作的公共接口(一组API),定义了用来访问数据库的标准Java类库,(java.sql,javax.sql)使用这些类库可以以一种标准的方法、方便地访问数据库资源。
-
JDBC为访问不同的数据库提供了一种统一的途径,为开发者屏蔽了一些细节问题。
-
JDBC的目标是使Java程序员使用JDBC可以连接任何提供了JDBC驱动程序的数据库系统,这样就使得程序员无需对特定的数据库系统的特点有过多的了解,从而大大简化和加快了开发过程。
-
如果没有JDBC,那么Java程序访问数据库时是这样的:
1.4 JDBC体系结构
JDBC接口(API)包括两个层次:
-
面向应用的API:Java API,抽象接口,供应用程序开发人员使用(连接数据库,执行SQL语句,获得结果)。
-
面向数据库的API:Java Driver API,供开发商开发数据库驱动程序用。
1.5 JDBC程序编写步骤
概念讲得也差不多了,那我们直接上代码看看操作流程!
获取数据库连接
获取数据库也可以分成好几个步骤,可以慢慢的去熟悉,以后用多了,就直接拿来用了
首先得导一个那种类似于插件的东西,如下图所示的mysql5.1.7
2.1加载与注册JDBC驱动
-
加载驱动:加载 JDBC 驱动需调用 Class 类的静态方法 forName(),向其传递要加载的 JDBC 驱动的类名
-
Class.forName(“com.mysql.jdbc.Driver”);
-
-
注册驱动:DriverManager 类是驱动程序管理器类,负责管理驱动程序
-
使用DriverManager.registerDriver(com.mysql.jdbc.Driver)来注册驱动
-
通常不用显式调用 DriverManager 类的 registerDriver() 方法来注册驱动程序类的实例,因为 Driver 接口的驱动程序类都包含了静态代码块,在这个静态代码块中,会调用
-
2.2 要素二:URL
-
JDBC URL 用于标识一个被注册的驱动程序,驱动程序管理器通过这个 URL 选择正确的驱动程序,从而建立到数据库的连接。
-
JDBC URL的标准由三部分组成,各部分间用冒号分隔。
-
jdbc:子协议:子名称
-
协议:JDBC URL中的协议总是jdbc
-
子协议:子协议用于标识一个数据库驱动程序
-
子名称:一种标识数据库的方法。子名称可以依不同的子协议而变化,用子名称的目的是为了定位数据库提供足够的信息。包含主机名(对应服务端的ip地址),端口号,数据库名
-
几种常用数据库的 JDBC URL
-
MySQL的连接URL编写方式:
-
jdbc:mysql://主机名称:mysql服务端口号/数据库名称?参数=值&参数=值
-
jdbc:mysql://localhost:3306/test
-
jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8(如果JDBC程序与服务器端的字符集不一致,会导致乱码,那么可以通过参数指定服务器端的字符集)
-
jdbc:mysql://localhost:3306/test?user=root&password=123456
-
-
Oracle 9i的连接URL编写方式:
-
jdbc:oracle:thin:@主机名称:oracle服务端口号:数据库名称
-
jdbc:oracle:thin:@localhost:1521:test
-
-
SQLServer的连接URL编写方式:
-
jdbc:sqlserver://主机名称:sqlserver服务端口号:DatabaseName=数据库名称
-
jdbc:sqlserver://localhost:1433:DatabaseName=atguigu
-
2.3 要素三:用户名和密码
-
user,password可以用“属性名=属性值”方式告诉数据库
-
可以调用 DriverManager 类的 getConnection() 方法建立到数据库的连接
其中,配置文件声明在工程的src目录下:【jdbc.properties】
下面直接上我们的连接方式:
@Test
public void testConnection5() throws Exception {
//1.加载配置文件
InputStream is = ConnectionTest.class.getClassLoader().getResourceAsStream("jdbc.properties");
Properties pros = new Properties();
pros.load(is);
//2.读取配置信息
String user = pros.getProperty("user");
String password = pros.getProperty("password");
String url = pros.getProperty("url");
String driverClass = pros.getProperty("driverClass");
//3.加载驱动
Class.forName(driverClass);
//4.获取连接
Connection conn = DriverManager.getConnection(url,user,password);
System.out.println(conn);
}
同时也别忘记还要去释放资源:
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();
}
}
/*
**@haKu
* 关闭资源的操作
*
*/
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();
}
}
通用的操作代码
增删改
接下来我们放上一个实际性的操作,如果通过JDBC来实现对数据库进行增删改的操作,为了方便起见,我们就直接放上了通用的增删改操作!
//通用的增删改操作
public void update(String sql,Object ...args) {
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);
}
}
代码:查询单条记录
通用的查询一条数据,并且附上测试结果,首先我们先看看获取一条记录的方法怎么敲写的:
/*
**@haKu
* 使用PreparedStatement 实现针对于不同表的通用的查询,返回一条记录
*
*
*/
public <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();
int columnCount=rsmd.getColumnCount();
if (rs.next()){
//这个位置的对象,得是通用的
//通用类型
T t = clazz.newInstance();
for (int i = 0; i <columnCount ; i++) {
Object columnvalue = rs.getObject(i + 1);
//获取每个列的列名
String columnLabel = rsmd.getColumnLabel(i+1);
//给 t对象指定某个属性,赋值为columnName: 通过反射
Field field = clazz.getDeclaredField(columnLabel);
field.setAccessible(true);
field.set(t,columnvalue);
}
return t;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.closeResource(conn,ps,rs);
}
return null;
}
测试的代码:
@Test
public void testGetInstance(){
String sql="select id,name,email from customers where id=?";
Customer customer=getInstance(Customer.class,sql,1);
System.out.println(customer);
String sql1="select order_id orderId,order_name orderName,order_date orderDate from `order` where order_id=?";
Order order=getInstance(Order.class,sql1,1);
System.out.println(order);
}
测试结果图:
获取多条数据呢,换汤不换药,只要是知道一条是怎么拿到的,多条可谓是 锦上添花的事儿!
简单点想,就像是放到集合里面不就可以看全部的嘛,所以也不是很难,加油 相信自己!
代码:多条记录的查询
代码如下:
public <T> List<T> getForList(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();
int columnCount=rsmd.getColumnCount();
//创建集合对象
ArrayList<T> list = new ArrayList<T>();
while (rs.next()){
//这个位置的对象,得是通用的
//通用类型
T t = clazz.newInstance();
for (int i = 0; i <columnCount ; i++) {
Object columnvalue = rs.getObject(i + 1);
//获取每个列的列名
String columnLabel = rsmd.getColumnLabel(i+1);
//给 t对象指定某个属性,赋值为columnName: 通过反射
Field field = clazz.getDeclaredField(columnLabel);
field.setAccessible(true);
field.set(t,columnvalue);
}
list.add(t);
}
return list;
} 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<Customer> list=getForList(Customer.class,sql,12);
list.forEach(System.out::println);
}
测试结果:
测试结果里面没有十一是因为,我的表里面本来就不存在id为11的条目数据,所以大可放心的观看代码。
今天的学习就到此结束了,感谢大家的陪伴,又是收获满满的一天,一定会在学习的道路上越走越强的!!!
文章评论