JDBC概述
什么是持久化?(persistence)
持久化(persistence):把数据保存到课掉电式存储设备中以供之后使用。
大多数情况下,特别是企业级应用,数据持久化意味着将内存中的数据保存到硬盘上加以“固化”,而持久化的实现过程大多通过各种关系数据库来完成。持久化的主要应用是讲内存中的数据存储在数据库中,当然可以存储在磁盘文件、xml数据文件中。
JPA:javaEE的规范,Java Persistence Api:java的持久化API,hibernate实现了该规范(xml/注解)
·························------------------------------------------------------------------------------
在java中,数据库存取技术只能通过jdbc访问数据库:
Jdbc访问数据库的形式主要有两种:
1》 直接使用jdbc的API去访问数据库服务器(MySQL/Oracle)
2》 间接使用jdbc的API去访问数据库服务器。
第三方O/R Mapping工具,如hibernate,mybatis等(底层依然是JDBC)
JDBC是java访问数据库的基石,其他技术都是对JDBC的封装。
-------------------------------------------------------------------------------
JDBC(java database connectivity):
是一种用于执行SQL语句的javaAPI,可以为多种关系数据库提供统一访问,它由一组用java语言编写的类和接口组成。
JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。
JDBC喂访问不通的数据库提供了一种统一的途径,为开发这屏蔽了一些细节问题。
JDBC的目标是使java程序员使用JDBC可以连接任何提供了JDBC驱动程序的数据库系统,这样就使得程序员无需对特定的数据库系统的特点有过多的了解,从而大大简化和加快了开发过程。
总结:JDBC本身是java连接数据库的一个标准,是进行数据库链接的抽象层,由java编写的一组类和接口组成,接口的实现由各个数据库厂商来完成---驱动包
------------------------------------------------------------------------------
JDBC的版本:
JDBC隶属于javaSE的范畴,伴随着javaSE的版本升级。
Java6开始:JDBC4.0有一个新特性—无需加载注册驱动
Java7开始:JDBC4.1:RowSetProvider工具类。
-------------------------------------------------------------------------------JDBC的API在哪里---》JDK的API中
Java.sql包装的就是JDBC中的API 。
各大数据库厂商就回对JDBC的API提供实现类---》驱动包
注意:在开发中(编写的java代码)使用到的关于JDBC的类/接口,全部引入的是java.sql包/javax.sql包中的。
千万不要直接使用com.mysql..Xxx类。
面向接口编程:
Jdbc接口变量 =new MySQL实现();
变量=new oracle实现();
二、获取数据库链接
准备工作:
1.拷贝MySQL的驱动包到项目中去:mysql-connector-java-5.1.13-bin.jar
2.选中jar包build path,告诉项目去哪里去找字节码文件。
注意:千万不要拷贝成MySQL驱动的压缩文件,如mysql-connector-java-5.1.13-bin.zip
验证已经获取连接:可以在MySQL控制台,使用命令:show processlist;查看MySQL运行过程。
从java6(JDBC4.0)开始,可以不用再加载注册驱动。直接通过DriverManager获取连接对象。
为啥不用加载注册驱动了?
从java6开始,规范要求每一个JDBC驱动的包都必须带有META-INF/services/java.sql.Driver文件。
程序会自动去META-INF/services/java.sql.Driver 下读取驱动的全限定名,此时程序员不需要再去写Class.forName的代码。
开发建议:依然还是建议手动的加载注册驱动,因为在web中这个是必须的。
package com.lixing.day1._1_conn;
import java.sql.Connection;
import java.sql.DriverManager;
import org.junit.Test;
/*
* 获取JDBC的连接对象的步骤:贾琏
* 1:加载注册驱动
*Class.forName("com.mysql.jdbc.Driver");
* ①:在classpath中加载com.mysql.jdbc.Driver类
* ②:类中有静态代码块,使用驱动管理器注册了MySQL的驱动
* 2.使用DriverManager获取连接
*DriverManager.getConnection(String url, String user, String password)
*url:jdbc:mysql://localhost:3306/jdbcdemo 协议://IP:端口/数据库名称
* user:用户名
* password:密码
* */
//测试获取连接对象
public class ConnTest {
@Test
public voidtestGetConnBy40() throws Exception {
//1:加载注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2:获取连接对象
Connectionconn = DriverManager
.getConnection("jdbc:mysql://localhost:3306/jdbcdemo","root", "admin");
System.out.println(conn);
}
}
三、常见的JDBC API
①:
Connection接口:表示连接对象
Statement createStatement() :创建执行静态SQL的对象
PreparedStatementprepareStatement(String sql) :预编译一个SQL模板(带有?)
②:
Statement接口:执行静态SQL的语句对象
int executeUpdate(String sql) :执行DDL和DML操作的SQL
如果SQL是DDL则返回0,DML则返回受影响的行数
ResultSet executeQuery(String sql) :执行DQL语句,返回结果集对象
③:
ResultSet 接口:表示执行DQL语句得到的查询结果的封装
booleannext():尝试往下移动一行,成功返回true,否则返回false
Xxx.getXxx(int/String)根据列号/列名称获取当前行的 数据
Xxx表示的是数据的类型 如:long/int/String/Date等
④:
PreparedStatement接口:执行预编译SQL的语句对象
int executeUpdate() :执行DDL和DML操作的SQL
如果SQL是DDL则返回0,DML则返回受影响的行数
ResultSet executeQuery() :执行DQL语句,返回结果集对象
执行SQL之前,必须给所有的占位符赋值,通过使用以下方法:
void setXxx(int index, Xxx value);
Xxx表示的是数据的类型 如:long/int/String/Date等
JDBC中的索引是从1开始
四、DDL操作
需求:使用JDBC 在数据库中创建t_student表,该表包含id,name,age3个列
操作数据库的口诀:贾琏欲执事
1:加载注册驱动
2:获取连接对象
3:创建语句对象
4:执行SQL
5:释放资源
-------------------------------------------------------------------------------
CREATETABLE `t_student`(`id` BIGINT PRIMARY KEY AUTO_INCREMENT,`name`VARCHAR(255),`age` INT);
public class SQLTest {
@Test
public void testDdl() throws Exception {
String sql="CREATE TABLE`t_student`(`id` BIGINT PRIMARY KEY AUTO_INCREMENT,`name` VARCHAR(255),`age`INT)";
//1:加载注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2:获取连接对象
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbcdemo","root","admin");
//3:创建语句对象
Statement st = conn.createStatement();
//4:执行SQL
st.executeUpdate(sql);
//5:释放资源-----先开的后关,后开的先关
st.close();
conn.close();
}
}
五、异常处理
//java6方式
@Test
public voidtestHandleExceptionByJava6(){
String sql="CREATE TABLE`t_student`(`id` BIGINT PRIMARY KEY AUTO_INCREMENT,`name` VARCHAR(255),`age`INT)";
Connection conn = null;
Statement st = null;
try {
//1:注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2:获取连接对象
conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbcdemo","root", "admin");
//3:创建语句对象
st=conn.createStatement();
//4:执行sql语句
st.executeUpdate(sql);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
try {
if(st!=null){
st.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
try {
if(conn!=null){
conn.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
//java7方式
@Test
public voidtestHandleExceptionByJava7(){
Stringsql="CREATE TABLE `t_student`(`id` BIGINT PRIMARY KEYAUTO_INCREMENT,`name` VARCHAR(255),`age` INT)";
try (
//声明资源的代码----》实现AutoCloseable接口
Connection conn =DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbcdemo","root","admin");
Statement st=conn.createStatement();
){
conn.createStatement();
st.executeUpdate(sql);
} catch (Exception e) {
// TODO: handle exception
}
}
六、DML操作
//需求:往t_student表中插入一条数据----》黄姑娘,18
@Test
public void testSave() throws Exception{
String sql="INSERT INTOt_student(name,age) VALUES('黄姑娘',18)";
//操作数据库的口诀:贾琏欲执事
//1:加载注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2:获取连接对象
Connection conn =DriverManager.getConnection("jdbc:mysql:///jdbcdemo","root", "admin");
//3:创建语句对象
Statement st = conn.createStatement();
//4:执行SQL
st.executeUpdate(sql);
//5:释放资源
st.close();
conn.close();
}
//需求2:修改t_student表中id为2的数据姓名改为西门官人,年龄32
@Test
public void testUpdate() throwsException {
String sql="UPDATE t_student SETname='西门官人',age=32 WHERE id=2";
//操作数据库的口诀:贾琏欲执事
//1:加载注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2:获取连接对象
Connection conn = DriverManager.getConnection("jdbc:mysql:///jdbcdemo","root", "admin");
//3:创建语句对象
Statement st = conn.createStatement();
//4:执行SQL
st.executeUpdate(sql);
//5:释放资源
st.close();
conn.close();
}
//需求3:把t_student中id为2的记录删掉
@Test
public void testDelete() throwsException {
String sql="Delete from t_studentwhere id=2";
//操作数据库的口诀:贾琏欲执事
//1:加载注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2:获取连接对象
Connection conn =DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbcdemo","root","admin");
//3:创建语句对象
Statement st = conn.createStatement();
//4:执行SQL
st.executeUpdate(sql);
//5:释放资源
st.close();
conn.close();
}
注:DML操作和DDl操作步骤完全一样,仅仅是SQL语句不通而已;
发现问题:DDL和DML的操作的模板是一样的,仅仅是SQL不一样;
解决方案:把多个操作模板提取出来,提高项目的维护性
七、DQL操作
获取ResultSet中的数据步骤:
1:移动指针,先指向包含数据的行,使用next()
Next()方法的作用:尝试往下移动一行,有下一行则移动返回true,没有则返回false
2:获取行中的数据:
方式一:通过列的号码来获取,号码从1开始
XxxgetXxx(int columnindex)
方式二:通过列名来获取(唯一)
XxxgetXxx(String columnName)
Xxx表示的是数据类型,如:Long/int/String/Date等
//需求1 :查询product里面有多少条记录
public class DQLTest {
/*
mysql> SELECT count(id) from pruduct;
+---- -------+
| count(id) |
+----- ------+
| 21 |
+------ -----+
1 row in set
*/
@Test
public void test1() throws Exception {
//查询product里面有多少条记录
String sql="select count(id) countfrom product";
//聚合函数查询结果用long来接收
//1:加载注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2:获取连接对象
Connection conn =DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbcdemo","root", "admin");
//3:创建语句对象
Statement st = conn.createStatement();
//4:执行sql语句
ResultSet rs = st.executeQuery(sql);
//-----------解析结果集------------
while(rs.next()){
//long count=rs.getLong(1);//通过列号来取,1开始
//longcount=rs.getLong("count(id)");//通过列名来取
long count=rs.getLong("count");//通过别名来取
System.out.println(count);
}
//释放资源
rs.close();
st.close();
conn.close();
//需求2:查询product表中id为10的数据
@Test
public void test2() throws Exception {
/*
mysql> select * from product whereid=10;
+----+--------------------+--------+--------------+------------+---------+--
| id | productName | dir_id | salePrice |supplier | brand | cutoff | costPrice |
+----+--------------------+--------+--------------+------------+---------+---------+--------------+
| 10 | 罗技 | 2 | 135 | 罗技 | 罗技 | 0.92 | 69.8 |
+----+--------------------+--------+--------------+-------------+---------+-
1 row in set
*/
String sql="select * from productwhere id=10";
//1:加载注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2:获取连接对象
Connection conn =DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbcdemo","root", "admin");
//3:创建执行对象
Statement st = conn.createStatement();
//4:执行SQL语句
ResultSet rs = st.executeQuery(sql);
//5:处理结果集
while(rs.next()){
Long id = rs.getLong("id");
String name =rs.getString("productName");
BigDecimal salePrice =rs.getBigDecimal("salePrice");
System.out.println(id+":"+name+":"+salePrice);
}
//6:释放资源
rs.close();
st.close();
conn.close();
}
//需求3:查询整个表的商品记录
@Test
public void testName() throws Exception{
String sql="SELECT * FROMproduct";
//1:加载注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2:获取连接对象
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbcdemo","root", "admin");
//3:创建执行对象
Statement st = conn.createStatement();
//4:执行SQL语句
ResultSet rs = st.executeQuery(sql);
//5:处理结果集
while(rs.next()){
long id = rs.getLong("id");
String name = rs.getString("productName");
BigDecimal price =rs.getBigDecimal("salePrice");
System.out.println(id+":"+name+":"+price);
}
//6:释放资源
rs.close();
st.close();
conn.close();
}
java和mysql类型对应:
java.util.Date和java.sql.Date有什么关系:
java.sql.Date是java.util.Date的子类。
所以,以后在代码中依然使用java.util.Date(多态)
菜鸟总结,不当之处,敬请批评指正!