一、JDBC简介

1、SUN公司为了简化、统一对数据库的操作,定义了一套Java操作数据库的规范,称之为JDBC,JDBC(Java Data Base Connectivity,java数据库连接),由一些接口和类构成的API. J2SE的一部分,由java.sql,javax.sql包组成,开发还需要导入相应JDBC的数据库实现(即数据库驱动).

2、应用程序、JDBC API、数据库驱动级数据库之间的关系.

SUN公司定义标准也就是这些接口,数据库厂商实现这些接口,比如电脑显卡驱动是由显卡公司设计的驱动,实现了主板公司定义的标准,这样更换显卡时比较方便.

二、JDBC第一个程序

public class TestJDBC {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1、创建驱动
Class.forName("com.mysql.jdbc.Driver");
     //2、建立连接
Connection conn= DriverManager.getConnection(
          "jdbc:mysql://223.202.100.234:3306/exagoods_product", "globebuy","lijiang");
//3、创建语句
Statement s = conn.createStatement();
//4、执行语句
ResultSet rs = s.executeQuery("select * from shop");
//5、处理结果
while(rs.next()){
System.out.println(rs.getObject(1)+"--"+rs.getObject(2));
}
//6、释放资源
rs.close();
s.close();
conn.close(); //把socket关闭,不然数据库很快会挂掉
}
}

观察上面代码发现和URL编程如出一辙,其实原理相同,都是基于网络的应用层编程,jdbc使用的是jdbc协议,URL编程使用的是http协议,Mysql服务器类比Tomcat服务器,底层都是socket编程.

1、注册驱动

Class.forName("com.mysql.jdbc.Driver"); //推荐这种方式,不会对具体的驱动类产生依赖.
DriverManager.registerDriver(com.mysql.jdbc.Driver); //并会对具体的驱动类产生依赖.
System.setProperty("jdbc.drivers", "driver1:driver2"); //注册不太方便,所以很少使用.

2、数据库URL

url格式:
JDBC:子协议:子名称//主机名:端口/数据库名?属性名=属性值&…
User,password可以用“属性名=属性值”方式告诉数据库;
其他参数如:useUnicode=true&characterEncoding=UTF-8 注:localhost和默认端口可以省略,所以可能出现如下写法:
jdbc:mysql:///exagoods_product

3、程序详解—Connection

Jdbc程序中的Connection,它用于代表数据库的链接,Collection是数据库编程中最重要的一个对象,客户端与数据库所有交互都是通过connection对象完成的,这个对象的常用方法:
createStatement():创建向数据库发送sql的statement对象.
prepareStatement(sql) :创建向数据库发送预编译sql的PrepareSatement对象.
prepareCall(sql):创建执行存储过程的callableStatement对象.
setAutoCommit(boolean autoCommit):设置事务是否自动提交.
commit() :在链接上提交事务.
rollback() :在此链接上回滚事务.

4、程序详解—Statement

Jdbc程序中的Statement对象用于向数据库发送SQL语句, Statement对象常用方法:
executeQuery(String sql) :用于向数据发送查询语句.
executeUpdate(String sql):用于向数据库发送insert、update或delete语句
execute(String sql):用于向数据库发送任意sql语句
addBatch(String sql) :把多条sql语句放到一个批处理中.
executeBatch():向数据库发送一批sql语句执行.

statement存在sql注入攻击问题,例如登陆用户名采用'or 1=1 or name=',对于防范 SQL 注入,可以采用PreparedStatement取代Statement.statement和PreparedStatement区别:

PreperedStatement是Statement子类,它的实例对象可以通过调用Connection.preparedStatement()方法获得,相对于Statement对象而言:
•PreperedStatement可以避免SQL注入的问题.
•Statement会使数据库频繁编译SQL,可能造成数据库缓冲区溢出.PreparedStatement 可对SQL进行预编译,即将sql的编译放在Java代码端,从而提高数据库的执行效率.
•并且PreperedStatement对于sql中的参数,允许使用占位符的形式进行替换,简化sql语句的编写.

5、程序详解—ResultSet

1>Jdbc程序中的ResultSet用于代表Sql语句的执行结果.Resultset封装执行结果时,采用的类似于表格的方式.ResultSet 对象维护了一个指向表格数据行的游标,初始的时候,游标在第一行之前,调用ResultSet.next() 方法,可以使游标指向具体的数据行,进行调用方法获取该行的数据.

ResultSet既然用于封装执行结果的,所以该对象提供的都是用于获取数据的get方法:

获取任意类型的数据
getObject(int index)
getObject(string columnName)
获取指定类型的数据,例如:
getString(int index)
getString(String columnName)

2>ResultSet还提供了对结果集进行滚动的方法:

next():移动到下一行
Previous():移动到前一行
absolute(int row):移动到指定行
beforeFirst():移动resultSet的最前面.
afterLast() :移动到resultSet的最后面.

6、程序详解—释放资源

1>Jdbc程序运行完后,切记要释放程序在运行过程中,创建的那些与数据库进行交互的对象,这些对象通常是ResultSet, Statement和Connection对象.特别是Connection对象,它是非常稀有的资源,用完后必须马上释放,如果Connection不能及时、正确的关闭,极易导致系统宕机.Connection的使用原则是尽量晚创建,尽量早的释放.
2>为确保资源释放代码能运行,资源释放代码也一定要放在finally语句中.

7、基本的CRUD(创建、读取、更新、删除) 

//模板代码
Connection conn = null;
Statement st=null;
ResultSet rs = null;
try {
//获得Connection
//创建Statement
//处理查询结果ResultSet
} finally {
//释放资源ResultSet, Statement,Connection
}

ps:注意返回值的使用:

int num = st.executeUpdate(sql);
if(num>0){
System.out.println("插入成功!!!");
}

三、创建jdbcUtils类简化开发

//导包时注意不要导具体驱动的包
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 { private static Properties config = new Properties();
static {
try {
config.load(JdbcUtils.class.getClassLoader().getResourceAsStream(
"db.properties"));
Class.forName(config.getProperty("driver"));
} catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
} public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(config.getProperty("url"),
config.getProperty("username"), config.getProperty("password"));
} public static void release(Connection conn, Statement st, ResultSet rs) {
if (rs != null) {
try {
rs.close();
} catch (Exception e) {
e.printStackTrace();
}
rs = null;
}
if (st != null) {
try {
st.close();
} catch (Exception e) {
e.printStackTrace();
}
st = null;
}
if (conn != null) {
try {
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
//db.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/day14
username=root
password=root

//可以任意切换数据库而无需修改代码
#driver=oracle.jdbc.driver.OracleDriver
#url=jdbc:oracle:thin:@localhost:1521:orcl
#username=system
#password=itcast
//基本CRUDTest
public class CRUDTest { @Test
public void insert() throws SQLException{
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try{
conn = JdbcUtils.getConnection(); //oracle
st = conn.createStatement();
String sql = "insert into users(id,name,password) values(4,'eee','123')";
int num = st.executeUpdate(sql);
if(num>0){
System.out.println("插入成功!!!");
}
}finally{
JdbcUtils.release(conn, st, rs);
}
} @Test
public void update() throws SQLException{
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try{
conn = JdbcUtils.getConnection();
st = conn.createStatement();
String sql = "update users set name='fff' where id='4'";
int num = st.executeUpdate(sql);
if(num>0){
System.out.println("更新成功!!");
}
}finally{
JdbcUtils.release(conn, st, rs);
}
} @Test
public void delete() throws SQLException{
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try{
conn = JdbcUtils.getConnection();
st = conn.createStatement();
String sql = "delete from users where id=4";
int num = st.executeUpdate(sql);
if(num>0){
System.out.println("删除成功!!");
}
}finally{
JdbcUtils.release(conn, st, rs);
}
} public void find() throws SQLException{
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try{
conn = JdbcUtils.getConnection();
st = conn.createStatement();
String sql = "select id,name,password,email,birthday from users where id=1";
rs = st.executeQuery(sql);
User user = null;
if(rs.next()){
user = new User();
user.setId(rs.getInt("id"));
user.setName(rs.getString("name"));
user.setPassword(rs.getString("password"));
user.setEmail(rs.getString("email"));
user.setBirthday(rs.getDate("birthday"));
}
System.out.println(user);
}finally{
JdbcUtils.release(conn, st, rs);
}
} @Test
public void getAll() throws SQLException{
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try{
conn = JdbcUtils.getConnection();
st = conn.createStatement();
String sql = "select id,name,password,email,birthday from users";
rs = st.executeQuery(sql);
List list = new ArrayList();
while(rs.next()){
User user = new User();
user.setId(rs.getInt("id"));
user.setName(rs.getString("name"));
user.setPassword(rs.getString("password"));
user.setEmail(rs.getString("email"));
user.setBirthday(rs.getDate("birthday"));
list.add(user);
}
}finally{
JdbcUtils.release(conn, st, rs);
}
}
}

四、初步修改之前的用户模块,xml模拟数据库改为jdbc操作数据库,略.

ps: 涉及知识有web包结构、异常处理问题、JdbcUtils(结合配置文件简化代码)、DaoFactory(实现接口和实现分离,解耦合)、单例模式和工厂模式,代码见文件.

五、数据库分页

1、分页结构图,对象的封装思想,QueryInfo封装请求信息、QueryResurt封装dao层的查询信息、PageBean封装页面的数据.

ps:参考day15_customer项目,代码经典见文件.

六、使用JDBC处理大数据

在实际开发中,程序需要把大文本或二进制数据保存到数据库:
•clob和blob
•clob用于存储大文本.
•blob用于存储二进制数据,例如图像、声音、二进制文等.
对MySQL而言只有blob,而没有clob,mysql存储大文本采用的是Text.
/**读写大文本
create table testclob
(
id varchar(40) primary key,
resume text
);
*/
public class Demo1 { @Test
public void insert() throws SQLException, FileNotFoundException{
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null; try{
conn = JdbcUtils.getConnection();
String sql = "insert into testclob(id,resume) values(?,?)";
st = conn.prepareStatement(sql);
st.setString(1, "1"); File file = new File("src/1.txt");
FileReader reader = new FileReader(file);
st.setCharacterStream(2, reader, (int) file.length());
int num = st.executeUpdate();
if(num>0){
System.out.println("插入成功!!");
}
}finally{
JdbcUtils.release(conn, st, rs);
}
} @Test
public void read() throws SQLException, IOException{
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null; try{
conn = JdbcUtils.getConnection();
String sql = "select id,resume from testclob where id='1'";
st = conn.prepareStatement(sql);
rs = st.executeQuery();
if(rs.next()){
//String resume = rs.getString("resume");
Reader reader = rs.getCharacterStream("resume");
FileWriter writer = new FileWriter("c:\\1.txt");
try {
int len = 0;
char buffer[] = new char[1024];
while ((len = reader.read(buffer)) > 0) {
writer.write(buffer, 0, len);
}
} finally {
if (reader != null) {
reader.close();
}
writer.close();
}
}
}finally{
JdbcUtils.release(conn, st, rs);
}
}
}
/*
create table testblob
(
id varchar(40) primary key,
image blob
);
*/
public class Demo2 {
@Test
public void insert() throws SQLException, FileNotFoundException{
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try{
conn = JdbcUtils.getConnection();
String sql = "insert into testblob(id,image) values(?,?)";
st = conn.prepareStatement(sql);
st.setString(1, "1");
File file = new File("src/1.jpg");
FileInputStream in = new FileInputStream(file);
st.setBinaryStream(2, in, (int) file.length());
st.executeUpdate();
}finally{
JdbcUtils.release(conn, st, rs);
}
} @Test
public void read() throws SQLException, IOException{
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try{
conn = JdbcUtils.getConnection();
String sql = "select id,image from testblob where id='1'";
rs = conn.prepareStatement(sql).executeQuery();
if(rs.next()){
InputStream in = rs.getBinaryStream("image");
OutputStream out = new FileOutputStream("c:\\1.jpg");;
try {
int len = 0;
byte buffer[] = new byte[1024];
while ((len = in.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
} finally {
if (in != null)
in.close();
if (out != null)
out.close();
}
}
}finally{
JdbcUtils.release(conn, st, rs);
}
}
}

七、使用JDBC进行批处理

1、采用Statement.addBatch(sql)方式实现批处理:

•优点:可以向数据库发送多条不同的sql语句.

•缺点:SQL语句没有预编译.当向数据库发送多条相同语句,但仅参数不同的SQL语句时,需重复写上很多条SQL语句.

2、采用PreparedStatement.addBatch()实现批处理:(使用多)

•优点:发送的是预编译后的SQL语句,执行效率高.

•缺点:只能应用在SQL语句相同,但参数不同的批处理中.因此此种形式的批处理经常用于在同一个表中批量插入数据,或批量更新表的数据.

/*
create table testbatch
(
id varchar(40) primary key,
name varchar(40)
);
*/
public class Demo3 {
//实现批处理第一种方式
@Test
public void test1() throws SQLException{
Connection conn = null;
Statement st = null;
ResultSet rs = null; try{
conn = JdbcUtils.getConnection();
String sql1 = "insert into testbatch(id,name) values('1','aaa')";
String sql2 = "update testbatch set name='bbb' where id='1'"; st = conn.createStatement();
st.addBatch(sql1);
st.addBatch(sql2);
st.executeBatch();
st.clearBatch();
}finally{
JdbcUtils.release(conn, st, rs);
}
} //实现批处理的第二种方式
@Test
public void test2() throws SQLException{
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null; try{
conn = JdbcUtils.getConnection();
String sql = "insert into testbatch(id,name) values(?,?)"; //作批量插入 批量更新
st = conn.prepareStatement(sql); for(int i=1;i<=10000006;i++){
st.setString(1, i+"");
st.setString(2, "aa" + i);
st.addBatch();
if(i%1000==0){
st.executeBatch();
st.clearBatch();
}
}
st.executeBatch();
}finally{
JdbcUtils.release(conn, st, rs);
}
}
}

八、获得数据库自动生成的主键,仅对insert操作有效

/**
create table test
(
id int primary key auto_increment,
name varchar(40)
);
*/
public class Demo4 {
public static void main(String[] args) throws SQLException {
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null; try{
conn = JdbcUtils.getConnection();
String sql = "insert into test(name) values('aaa')";
st = conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
st.executeUpdate(); rs = st.getGeneratedKeys();
if(rs.next()){
System.out.println(rs.getInt(1));
} }finally{
JdbcUtils.release(conn, st, rs);
}
}
}

九、JDBC调用存储过程,金融领域用的多,安全.

// 调用存储过程
public static void main(String[] args) throws SQLException {
Connection conn = null;
CallableStatement st = null;
ResultSet rs = null;
try{
conn = JdbcUtils.getConnection();
st = conn.prepareCall("{call demoSp(?,?)}");
st.setString(1, "aaaaa");
st.registerOutParameter(2, Types.VARCHAR);
st.execute();
System.out.println(st.getString(2));
}finally{
JdbcUtils.release(conn, st, rs);
}
}
 

javaEE(10)_jdbc基本使用的更多相关文章

  1. JavaEE(10) - Session EJB的依赖注入、引用及任务调度

    1. EJB依赖注入 #1. EJB开发(Net Beans创建EJB Module, 项目名称:CallHello) Hello.java package org.crazyit.service; ...

  2. javaEE(13)_jdbc框架

    一.使用模板方法设计模式简化开发 模板方法设计模式,执行一个程序有很多步骤,将每次都要执行的共有的提取出来放到一个抽象父类中,变化的部分通过让子类传递参数过来或将这部分抽象为抽象方法让子类通过继承的方 ...

  3. java对象数组的概述和使用

    1 public class Student 2 { 3 // 成员变量 4 private String name; 5 private int age; 6 7 // 构造方法 8 public ...

  4. Apache 项目列表功能分类便于技术选型

    big-data (49):  Apache Accumulo  Apache Airavata  Apache Ambari  Apache Apex  Apache Avro  Apache Be ...

  5. java设计模式基础 - 解决某一类问题最行之有效的方法,框架是大的设计模式.

    一.单例模式(Singleton) 1.单例对象(Singleton)是一种常用的设计模式.在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在.这样的模式有几个好处: 1>某 ...

  6. 在eclipse中,用maven创建一个web项目工程

    1.在eclipse中用maven创建项目,右键new>>Maven Project 2.点击next继续 3.点击next继续,选择maven-archetype-webapp, 4.点 ...

  7. java 数组对象的应用

    public class Student 2 { 3 // 成员变量 4 private String name; 5 private int age; 6 7 // 构造方法 8 public St ...

  8. 使用eclipse创建maven时遇到的问题

    转自https://www.cnblogs.com/hongmoshui/p/7994759.html   1.在eclipse中用maven创建项目,右键new>>Maven Proje ...

  9. JavaEE中遗漏的10个最重要的安全控制

    本文由码农网 – 小峰原创翻译,转载请看清文末的转载要求,欢迎参与我们的付费投稿计划! JavaEE有一些超赞的内置安全机制,但它们远远不能覆盖应用程序要面临的所有威胁.很多常见攻击,例如跨站点脚本攻 ...

随机推荐

  1. laravel M层

    目录 App\Models   没有就自己创一个 创建对应控制器的php文件,首字母大写 <?php namespace App\Models; use Illuminate\Database\ ...

  2. OPENGL0_简介

    opengl定义: Open Graphics Library,开放图形程序接口,跨平台,跨语言.提供了与底层图形硬件的接口,是一个功能强大的底层图形库. opengl库种类: gl:核心库,常规,核 ...

  3. [Xcode 实际操作]七、文件与数据-(23)UI Testing系统界面测试功能的使用

    目录:[Swift]Xcode实际操作 本文将演示UI Testing系统界面测试功能的使用. 如果项目中尚未引入界面测试功能,请点击项目属性面板->[General]面板左下角的[+]图标 - ...

  4. [Xcode 实际操作]九、实用进阶-(32)项目的打包上传和提交审核以及下架处理

    目录:[Swift]Xcode实际操作 本文将演示如何将一个应用程序进行打包上传,并提交审核以及下架处理. 点击项目[DemoApp]->[Build Settings]编译设置->[Pr ...

  5. Hive_Hive的管理_远程服务

    远程服务启动方式 - 端口号10000 - 启动方式: #hive --service hiveserver & 以JDBC或ODBC的程序登陆到hive中操作数据时,必须选用远程服务启动方式 ...

  6. 04.Javascript——入门一些方法记录之iterable

    遍历Array可以采用下标循环,遍历Map和Set就无法使用下标.为了统一集合类型,ES6标准引入了新的iterable类型,Array.Map和Set都属于iterable类型. 具有iterabl ...

  7. CSS修改Autocomplete样式

    举个场景:在用户登录成功的时候,浏览器有时候会咨询你是否记住密码,当你记住密码下次登录的时候,标签会自动填充,但是这样会造成样式不统一,解决办法如下: input:-webkit-autofill, ...

  8. Ubuntu安装LAMP

    1.安装apache2 sudo apt-get install apache2 sudo apt-get install apache2 Apache安装成功后,/var/www/默认作为web的根 ...

  9. datetimepicker 插件位置问题解决经验

    使用dadetimepicker进行时间选择是个很不错的选择,但是美中不足的是该插件在chrome中显示弹框的时候有时会出现位置错位的现象,而在IE中则没有这种现象,视图如图1 图1 查阅了网上的资料 ...

  10. uvm_reg_defines——寄存器模型(四)

    文件: src/marcos/uvm_reg_defines 类: 无 该文件是寄存器模型src/reg/* 文件对于的宏文件,主要定义了寄存器地址位宽,寄存器数据位宽,字节的大小.计算机从最初的8, ...