JDBC(Java Database Connectivity)是一个独立于特定数据库管理系统、通用的SQL数据库存取和操作的公共接口(一组API),定义了用来访问数据库的标准Java类库,(java.sql,javax.sql)使用这些类库可以以一种标准的方法、方便地访问数据库资源。JDBC为访问不同的数据库提供了一种统一的途径,为开发者屏蔽了一些细节问题。JDBC的目标是使Java程序员使用JDBC可以连接任何提供了JDBC驱动程序的数据库系统,这样就使得程序员无需对特定的数据库系统的特点有过多的了解,从而大大简化和加快了开发过程。如果没有JDBC,那么Java程序访问数据库时是这样的:

有了JDBC,Java程序访问数据库时是这样的:

JDBC接口(API)包括两个层次:
JDBC程序编写步骤:

获取连接的四要素:
JDBC驱动
在当前项目模块下建里lib目录,

然后按右键,选择Add as Library选项。

URL
JDBC URL的标准由三部分组成,各部分间用冒号分隔。
public class GetConnection {
@Test
public void test1() {
//获取连接方式一
try {
//1. 提供java.sql.jdbc.Driver的实现类
Driver driver = null;
driver = new com.mysql.jdbc.Driver();
//2.提供url
String url = "jdbc:mysql://localhost:3306/test";
//3.提供用户和密码
Properties properties = new Properties();
properties.put("user", "root");
properties.put("password", "123");
//获取连接
Connection connect = driver.connect(url, properties);
System.out.println(connect);
} catch (SQLException e) {
e.printStackTrace();
}
}
//方式二
@Test
public void test() {
try {
//1.实例化Driver
String className = "com.mysql.jdbc.Driver";
Class<?> clazz = Class.forName(className);
Driver driver = (Driver) clazz.newInstance();
//2.提供url
String url = "jdbc:mysql://localhost:3306/test";
//3.提供用户和密码
Properties properties = new Properties();
properties.put("user", "root");
properties.put("password", "123");
//获取连接
Connection connect = driver.connect(url, properties);
System.out.println(connect);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
//方式三
@Test
public void test3(){
//mysql连接的4要素
String driverName = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/test";
String user = "root";
String password = "123";
try {
//1.实例化Driver
Class<?> clazz = Class.forName(driverName);
Driver driver = (Driver)clazz.newInstance();
//2.注册驱动
DriverManager.registerDriver(driver);
//3.获取连接
Connection connection = DriverManager.getConnection(url, user, password);
System.out.println(connection);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
//方式四
@Test
public void test4(){
//mysql连接的4要素
String driverName = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/test";
String user = "root";
String password = "123";
try {
//1.实例化Driver
// Class<?> clazz = Class.forName(driverName);
// Driver driver = (Driver)clazz.newInstance();
//2.注册驱动
Class.forName(driverName);
//3.获取连接
Connection connection = DriverManager.getConnection(url, user, password);
System.out.println(connection);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
//方式五:加载配置文件的方式
@Test
public void test5(){
InputStream in = null;
Properties ps = null;
try {
in = GetConnection.class.getClassLoader().getResourceAsStream("jdbc.properties");
ps = new Properties();
ps.load(in);
//读取配置文件
String user = ps.getProperty("user");
String password = ps.getProperty("password");
String url = ps.getProperty("url");
String driverClass = ps.getProperty("driverClass");
//加载驱动
Class.forName(driverClass);
//获取连接
Connection connection = DriverManager.getConnection(url, user, password);
System.out.println(connection);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
数据库连接被用于向数据库服务器发送命令和 SQL 语句,并接受数据库服务器返回的结果。其实一个数据库连接就是一个Socket连接。
在 java.sql 包中有 3 个接口分别定义了对数据库的调用的不同方式:
Statement版
使用Statement来实现CURD有如下的弊端:
问题一:存在拼串操作,繁琐
问题二:存在SQL注入问题
public class StatementTest {
public static void main(String ...args){
Scanner scan = new Scanner(System.in);
System.out.println("请输入用户名:");
String userName = scan.nextLine();
System.out.println("请输入密码:");
String password = scan.nextLine();
//String sql = "SELECT user,password FROM user_table WHERE user = 'aa' OR ( true OR ( true AND password = '123'))";
String sql = "SELECT user,password FROM user_table WHERE user = '" + userName + "' AND password = '" + password + "'";
System.out.println(sql);
User user = get(sql, User.class);
if(user != null){
System.out.println(user);
}else{
System.out.println("登录失败!!");
}
}
public static <T> T get(String sql, Class<T> clazz){
T t = null;
Connection conn = null;
Statement stat = null;
ResultSet rs = null;
try{
//加载配置文件
InputStream in = StatementTest.class.getClassLoader().getResourceAsStream("jdbc.properties");
Properties ps = new Properties();
ps.load(in);
//获取配置信息
String driverClass = ps.getProperty("driverClass");
String url = ps.getProperty("url");
String user = ps.getProperty("user");
String password = ps.getProperty("password");
//注册驱动
Class.forName(driverClass);
//获取连接
conn = DriverManager.getConnection(url, user, password);
//创建Statement对象,并执行sql
stat = conn.createStatement();
rs = stat.executeQuery(sql);
//获取元数据
ResultSetMetaData metaData = rs.getMetaData();
//获取列数
int colCnt = metaData.getColumnCount();
if(rs.next()){
t = clazz.newInstance();
for (int i = 0; i < colCnt; i++) {
//获取列的别名
String label = metaData.getColumnLabel(i + 1);
//依据列名获取数据
Object colVal = rs.getObject(label);
//属性值封装进对象
Field field = clazz.getDeclaredField(label);
field.setAccessible(true);
field.set(t,colVal);
}
}
return t;
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} finally {
if(rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(stat != null){
try {
stat.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return null;
}
}
PreparedStatement版
可以通过调用 Connection 对象的 preparedStatement(String sql) 方法获取 PreparedStatement 对象
PreparedStatement 接口是 Statement 的子接口,它表示一条预编译过的 SQL 语句。
PreparedStatement 对象所代表的 SQL 语句中的参数用问号(?)来表示,调用 PreparedStatement 对象的setXxx() 方法来设置这些参数. setXxx() 方法有两个参数,第一个参数是要设置的 SQL 语句中的参数的索引(从 1开始),第二个是设置的 SQL 语句中的参数的值。
public class PreparedStatementTest {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("请输入用户名:");
String userName = scan.nextLine();
System.out.println("请输入密码:");
String password = scan.nextLine();
//String sql = "SELECT user,password FROM user_table WHERE user = 'aa' OR ( true OR ( true AND password = '123'))";
String sql = "SELECT user,password FROM user_table WHERE user = '" + userName + "' AND password = '" + password + "'";
System.out.println(sql);
User user = get(sql, User.class);
if(user != null){
System.out.println(user);
}else{
System.out.println("登录失败!!");
}
}
public static <T> T get(String sql, Class clazz,String ... args){
T t = null;
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
InputStream is = PreparedStatementTest.class.getClassLoader().getResourceAsStream("jdbc.properties");
Properties ps = new Properties();
ps.load(is);
//获取配置信息
String driverClass = ps.getProperty("driverClass");
String url = ps.getProperty("url");
String user = ps.getProperty("user");
String password = ps.getProperty("password");
//注册驱动
Class.forName(driverClass);
//获取连接
conn = DriverManager.getConnection(url, user, password);
PreparedStatement pres = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
pres.setObject(i + 1, args[i]);
}
rs = pres.executeQuery();
//获取元数据
ResultSetMetaData metaData = rs.getMetaData();
//获取列数
int colCnt = metaData.getColumnCount();
if(rs.next()){
t = (T) clazz.newInstance();
for (int i = 0; i < colCnt; i++) {
//获取列的别名
String label = metaData.getColumnLabel(i + 1);
//依据列名获取数据
Object colVal = rs.getObject(label);
//属性值封装进对象
Field field = clazz.getDeclaredField(label);
field.setAccessible(true);
field.set(t,colVal);
}
}
return t;
} catch (IOException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
}
ResultSet
ResultSetMetaData
当需要成批插入或者更新记录时,可以采用Java的批量更新机制,这一机制允许多条语句一次性提交给数据库批量处
理。通常情况下比单独提交处理更有效率
JDBC的批量处理语句包括下面三个方法:
addBatch(String):添加需要批量处理的SQL语句或是参数;
executeBatch():执行批量处理语句;
clearBatch():清空缓存的数据
public class BatchProccessTest {
@Test
public void test1() throws SQLException {
Connection conn = JDBCUtils.getConnection();
String sql = "INSERT INTO goods(name) VALUES (?)";
PreparedStatement ps = conn.prepareStatement(sql);
long start = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {
ps.setObject(1, "name_" + i);
ps.executeUpdate();
}
long end = System.currentTimeMillis();
System.out.println("共用时:" + (end - start));
}
@Test
public void test2() throws SQLException {
Connection conn = JDBCUtils.getConnection();
conn.setAutoCommit(false);
String sql = "INSERT INTO goods(name) VALUES (?)";
PreparedStatement ps = conn.prepareStatement(sql);
long start = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {
ps.setObject(1, "name_" + i);
ps.addBatch();
if((i + 1) % 500 == 0){
ps.executeBatch();
ps.clearBatch();
}
}
conn.commit();
long end = System.currentTimeMillis();
System.out.println("共用时:" + (end - start));
}
}
在使用开发基于数据库的web程序时,传统的模式基本是按以下步骤:
C3P0连接池
public class C3P0Test {
@Test
public void test1() throws PropertyVetoException, SQLException {
//方式一
ComboPooledDataSource cpds = new ComboPooledDataSource();
cpds.setDriverClass("com.mysql.jdbc.Driver");
cpds.setJdbcUrl("jdbc:mysql://localhost:3306/test");
cpds.setUser("root");
cpds.setPassword("123");
cpds.setMaxPoolSize(10);
Connection conn = cpds.getConnection();
System.out.println(conn);
}
@Test
public void test2() throws SQLException {
//方式二
ComboPooledDataSource cpds = new ComboPooledDataSource("c3p0");
Connection conn = cpds.getConnection();
System.out.println(conn);
}
}
配置文件c3p0-config.xml如下:
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<named-config name="hellc3p0">
<!-- 提供获取连接的4个基本信息 -->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/test</property>
<property name="user">root</property>
<property name="password">123</property>
<!-- 进行数据库连接池管理的基本信息 -->
<!-- 当数据库连接池中的连接数不够时,c3p0一次性向数据库服务器申请的连接数 -->
<property name="acquireIncrement">5</property>
<!-- c3p0数据库连接池中初始化时的连接数 -->
<property name="initialPoolSize">10</property>
<!-- c3p0数据库连接池维护的最少连接数 -->
<property name="minPoolSize">10</property>
<!-- c3p0数据库连接池维护的最多的连接数 -->
<property name="maxPoolSize">100</property>
<!-- c3p0数据库连接池最多维护的Statement的个数 -->
<property name="maxStatements">50</property>
<!-- 每个连接中可以最多使用的Statement的个数 -->
<property name="maxStatementsPerConnection">2</property>
</named-config>
</c3p0-config>
dbcp连接池
public class dbcpTest {
@Test
public void test1() throws SQLException {
//方式一
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/test");
dataSource.setUsername("root");
dataSource.setPassword("123");
Connection conn = dataSource.getConnection();
System.out.println(conn);
}
@Test
public void test2() throws Exception {
//方式二
FileInputStream is = new FileInputStream("src/dbcp.properties");
Properties ps = new Properties();
ps.load(is);
DataSource dataSource = BasicDataSourceFactory.createDataSource(ps);
Connection conn = dataSource.getConnection();
System.out.println(conn);
}
}
dbcp.properties配置文件:
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test
username=root
password=123
Druid(德鲁伊)数据库连接池
public class DruidTest {
@Test
public void test() throws Exception {
Properties pros = new Properties();
InputStream is = new FileInputStream("src/druid.properties");
pros.load(is);
DataSource dataSource = DruidDataSourceFactory.createDataSource(pros);
Connection conn = dataSource.getConnection();
System.out.println(conn);
}
}
druid.properties配置文件
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test
username=root
password=123