Java小技能:Java Data Base Connectivity

128 阅读6分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第30天,点击查看活动详情

引言

JDBC是一种用来在Java程序中执行SQL的API,它为java连接数据库提供了一组接口和类,可以为多种关系数据库提供统一访问。

SUN公司只是在JDBC当中定义了具体的接口,而JDBC接口的具体的实现是由数据库提供厂商去写具体的实现, 比如说Connection对象,不同的数据库的实现方式是不同的。

I. 预备知识

1.1 JDBC

JDBC有一组应用程序的API,用来开发java连接数据库的应用程序;jdbc驱动api提供给数据库厂商,数据库厂商负责实现底层的编码。

1.2 对象关系映射(ORM)

使用传统的JDBC的项目已经越来越少了,曾经的model1和model2已经被MVC给代替了。如果用传统的JDBC写项目你不得不去管理你的数据连接、事物等。 而用ORM框架一般程序员只用关心执行SQL和处理结果集就行了。比如SpringJdbcTemplateHibernateHibernateTemplate提供了一套对dao操作的模版,对JDBC进行了轻量级封装。开发人员只需配置好数据源事物之后,开发仅需要提供SQL、处理SQL执行后的结果,其他的事情都交给框架去完成了。

ORM(Object Relational Mapping)框架采用元数据来描述对象与关系映射的细节,元数据一般采用XML格式,并且存放在专门的对象一映射文件中。

只要提供了持久化类与表的映射关系,ORM框架在运行时就能参照映射文件的信息,把对象持久化到数据库中。

当前ORM框架主要有五种:Hibernate(Nhibernate)iBatismybatisEclipseLinkJFinal

JPA全称Java Persistence API.JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中,是一个ORM规范,Hibernate是JPA的具体实现。

1.3 Java对象持久化(Java Data Object)

JDO(Java Data Object )是Java对象持久化的规范,用于存取某种数据仓库中对象的标准化API。

JPA可以依靠JDBC对JDO进行对象持久化,而ORM只是JPA当中的一个规范,我们常见的Hibernate、Mybatis和TopLink都是ORM的具体实现。

1.4 传统的JDBC

完成一次查询操作,java和数据库的交互操作:

  • 准备JDBC驱动
  • 加载驱动
  • 获取连接
  • 预编译SQL
  • 执行SQL
  • 处理结果集
  • 依次释放连接

II JDBC使用步骤

连接数据库的过程:JDBC Api ->driver;

2.1 准备连接数据库的相关数据

  1. 获得当前数据库连接的用户名和密码

  2. 获得数据库服务器的地址(ip)

  3. 获得数据库连接的端口号: oracle默认的是1521,mysql默认端口号是3306。

  4. 数据库的实例sid,即数据库名称。

  5. 获得连接字符串: url=jdbc:oracle:thin:@ip:port:sidurl=jdbc:mysql:@ip:port:sid

  6. 获得对应数据库的驱动: classes12.jar或ojdbc14.jar

2.2 书写jdbc程序步骤

  • 加载oracle驱动:导入oracle数据库的驱动oracle.jdbc.OracleDriver或者oracle.jdbc.driver.OracleDriver
class.forname("oracle.jdbc.OracleDriver");//通过反射加载驱动程序,在内存中创建oracleDriver的实例

  • 通过驱动管理器获得连接对象
Connection conn=DriverManager.getConnection()url,user,password;;//通过驱动管理器获得连接对象

  • 创建statement或preparestatement对象

生成statement实现类对象来编译sql,并将sql语句输送到数据库

// 方式一
Statement stmt=conn.createStatemenr();
//方式二
PreparedStatement pstmt=conn.prepareStatement(sql);//sql字符型不用加分号来结束
  • 执行sql,接收返回结果
//方式一:
ResultSet rs=stmt.executeQuery(sql);;

//方式二:
ResultSet rs=pstmt.executeQuery();

  • 循环遍历结果集
while(rs.next()){
 int empno=rs.getInt(String columnName);

}
  • 在finally中关闭资源
if(rs!=null){rs.close();}

if(pstmt!=null){pstmt.close();}

if(conn!=null){rconnclose();}

  1. prepareCall(String sql); 用于调用存储过程

  2. conn.setAutoCommit(false); 设置当前jdbc的事物处理为手动

conn.rollback();

conn.commit();

2.3 代码示例

package com.iosre.jdbc;
 
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
 
public class JDBCDemp {
	
	public static void main(String[] args) {
		jdbcTest(5438,"hello");
	}
	
	public static void jdbcTest(int id,String name){
		String url="jdbc:oracle:thin:@localhost:1521:XE";
		String user="hello";
		String password="123456";
		//String sql="delete from emp where empno="+id;
		String sql = "insert into emp(empno,ename) values("+id+",'"+name+"')";
		System.out.println(sql);
		Connection  conn=null;
		PreparedStatement pstmt=null;
		ResultSet rs =null;
		//1.通过反射加载驱动程序,驱动程序的类名,在内存中创建驱动程序的对象
		//oracle.jdbc.OracleDriver  
		//或者  oracle.jdbc.driver.OracleDriver
		try {
			Class.forName("oracle.jdbc.OracleDriver");
			//new oracle.jdbc.OracleDriver();
			conn = DriverManager.getConnection(url, user, password);
			//生成statement对象编译SQL
			//pstmt = conn.prepareStatement("select * from emp");
			
			Statement stmt = conn.createStatement();
			//执行SQL
			//rs = stmt.executeQuery("select * from emp");
			int num = stmt.executeUpdate(sql);
			
			if(num>0){
				System.out.println("删除成功");
			}
			/*while(rs.next()){
				//int empno = rs.getInt("empno");
				int empno = rs.getInt(1);
				String ename = rs.getString(2);
				System.out.println(ename);
			}*/
			
		} catch (ClassNotFoundException e) {
			
			e.printStackTrace();
		} catch (SQLException e) {
			
			e.printStackTrace();
		}finally{
			try {
				if(rs!=null){rs.close();}
				if(pstmt!=null){pstmt.close();}
				if(conn!=null){conn.close();}
			
				} catch (SQLException e) {
					
					e.printStackTrace();
				}
			}
	}
}

2.4 封装jdbc代码

package com.zhongx.jdbc;
 
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
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 ConnectionUtil {
	private static String url;
	private static  String user;
	private static String password;
	private static String driver;
	private static Properties prop = new Properties();
	//通过配置文件读取数据库 连接信息 
	//加载驱动创建对应驱动实例
	static{
		try {
			InputStream is = new FileInputStream("src/com/zhongx/jdbc/db.properties");
			prop.load(is);
			url = prop.getProperty("url");
			user = prop.getProperty("user");
			password = prop.getProperty("password");
			driver = prop.getProperty("driver");
			Class.forName(driver);
			
		} catch (FileNotFoundException e) {
			
			e.printStackTrace();
		} catch (IOException e) {
			
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			
			e.printStackTrace();
		}
	}
	
	public static Connection getConnection() throws SQLException{
		return DriverManager.getConnection(url, user, password);
	}
	public static void close(Connection conn,Statement stmt,ResultSet rs) throws SQLException{
		if(rs!=null){rs.close();}
		if(stmt!=null){stmt.close();}
		if(conn!=null){conn.close();}
	}
}

注释版本

//driverClass=com.mysql.jdbc.Driver
		//1.获取Driver实现类的对象
//		Class clazz = Class.forName("com.mysql.jdbc.Driver");
		//1.读取配置文件信息
		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);

2.5 预编译sql

预编译sql会将sql语句预先编译号,执行的时候直接传递参数,不需要再次编译。

PreparedStatement是Statement的子接口,它与Statement的区别有:

  1. 程序的可读性和可维护性更好

  2. 更安全

  3. 执行效率高

  • PreparedStatement 允许数据库预编译sql语句,这样在随后的运行中可以节省时间,并增加了查询的可读性;
  • Statement每次执行sql语句相关的数据库都要执行sql语句的编译。

III JDBC涉及的类和接口

java.sql.Connection 接口

  • createStatement() 获得Statement
  • prepareStatement(String sql) 获得preparedStatement
  • prepareCall(String sql) 调用存储过程

java.sql.DriverManager 类

  • getConnection(String url, String user, String password)

java.sql.Statement 接口

  • executeQuery(String sql) 执行DQL语句
  • executeUpdate(String sql) 执行DML语句
  • executeBatch() 批处理执行SQL

java.sql.PreparedStatement 接口

  • setXXX方法 :用来动态传参

java.sql.ResultSet 接口

  • next() 默认ResultSet对象指向记录的光标在第一条的前面
  • getXXX(String/int) 获得对应字段的值
  • getInt() 接收整数类型
  • getDouble() 接收浮点数据
  • getString()接收字符串类型
  • sql.Date getDate() 接收Date类型数据字段

see also

gzh: iOS逆向