概念:java database connectivity,java连接数据库
- JDBC实质:官方定义了操作所有关系型数据库的规则(接口)。各个数据库厂商实现这套接口,提供数据库驱动jar包。我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。
coder--->java代码(jdbc接口)--->数据库驱动(mysql db2 oracle)--->mysql db2 oracle
快速入门
- 步骤
1.导入驱动jar包
2.注册驱动
3.获取数据库连接对象 Connection
4.定义sql
5.获取执行sql语句的对象statement
6.执行sql,接收结果
6.处理数据
7.释放资源
- 代码实现
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/panda?serverTimezone=UTC","root","123456");
String sql = "select * from company where company_id < 10";
Statement stat = conn.createStatement();
ResultSet resultSet = stat.executeQuery(sql);
while (resultSet.next()){
System.out.println(resultSet.getString("name"));
}
stat.close();
conn.close();
详解各个对象
1.DriverManager:驱动管理对象
- 功能:
1)注册驱动
static void registerDriver(Driver driver)
写代码:Class.forName("com.mysql.jdbc.Driver");
通过查看源码得知:在com.mysql.jdbc.Driver类中存在静态代码块
static {
try{
java.sql.DriverManager.registerDriver(new Driver());
}catch(SQLException E){
//...
}
}
注意:
msqyl5之后可以不注册驱动,在META-INF==>services==>java.sql.Driver 自动注册了。
2)获取数据库的连接
方法:static Connection getConnenction(String url,String user,String password)
参数:url=>指定连接的路径=>语法:jdbc:mysql://ip:port/databaseName
例子:jdbc:mysql://localhost:3306/db3
如果连接是本机的,端口号是3306,则可以缩写:jdbc:mysql:///databaseName
2.Connection:数据库连接对象
- 功能:
1)获取执行sql的对象
Statement createStatement()
PreparedStatement prepareStatement(String sql)
2)管理事务
开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务
提交事务:commit()
回滚事务:rollback()
3.Statement:执行静态sql的对象
boolean execute(String sql):
可以执行任意的sql
int excuteUpdate(String sql):
可以执行DML(insert,update,delete)、DDL(create,alter,drop)
返回值:影响的行数,可以通过返回值来检验DML是否执行成功,返回值>1则执行成功。
ResultSet executeQuery(String sql):
执行DQL(select)
4.ResultSet:结果集对象,封装查询对象
next():游标向下移动一个位置
getXxx(参数):获取数据
Xxx是数据类型
参数:int:代表列的序号;String:代表列的名称
注意:游标下移=>判断当前行是否最后一行末尾=>获取数据
5.PreparedStatement:执行动态sql的对象
SQL注入问题:在拼接sql时,有一些特殊sql的特殊关键字拼接,会造成安全问题
sql:select * from table where username='xxx' and password='a' or 'a'='a'
解决注入问题:使用ProparedStatement来解决
预编译sql:参数使用?作为占位符
抽取JDBC工具类
1.注册驱动也抽取
2.抽取一个方法获取连接对象
- 配置文件的方法:jdbc.properties
password=123456
name=root
url=jdbc\:mysql\://localhost\:3306/panda?serverTimezone\=UTC
driver=com.mysql.jdbc.Driver
- 静态代码块来获取配置文件
static{
try{
Properties pro = new Properties();
//没有初始化所以不能使用下面的方法获取配置文件 ==> pro.load(this.getClass().getClassLoader().getResourceAsStream("jdbc.properties"));
pro.load(new FileReader(JdbcUtil1.class.getClassLoader().getResource("jdbc.properties").getPath()));
url = pro.getProperty("url");
name = pro.getProperty("name");
password = pro.getProperty("password");
driver = pro.getProperty("driver");
}catch(Exception){}
}
- 获取Connection对象
Connection connection = null;
try {
Class.forName(driver);
connection = DriverManager.getConnection(url, name, password);
} catch (Exception e) {
e.printStackTrace();
}
return connection;
3.抽取一个方法释放资源
4.完整代码:
package test.jdbc;
import java.io.FileReader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class JdbcUtil1 {
private static String url;
private static String name;
private static String password;
private static String driver;
static {
try {
Properties pro = new Properties();
//没有初始化所以不能使用下面的方法获取配置文件 ==> pro.load(this.getClass().getClassLoader().getResourceAsStream("jdbc.properties"));
pro.load(new FileReader(JdbcUtil1.class.getClassLoader().getResource("jdbc.properties").getPath()));
url = pro.getProperty("url");
name = pro.getProperty("name");
password = pro.getProperty("password");
driver = pro.getProperty("driver");
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection getConnection() {
Connection connection = null;
try {
Class.forName(driver);
connection = DriverManager.getConnection(url, name, password);
} catch (Exception e) {
e.printStackTrace();
}
return connection;
}
public static void closeConnection(Statement statement, Connection connection) {
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
使用JDBC控制事务
- 事务:一个包含多个业务的操作。如果这个业务操作被事务管理,那么这些多个步骤要么同时成功,要么同时失败。
- 操作:
1.开启
2.提交
3.回滚
开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务
在写sql之前开启事务
提交事务:commit()
当所有sql语句执行完之后提交事务
回滚事务:rollback()
在catch中回滚事务
@Test
public void test3() {
Connection connection = JdbcUtil1.getConnection();
Statement statement = null;
//设置为false,开启事务
try {
connection.setAutoCommit(false);
statement = connection.createStatement();
int index = statement.executeUpdate("update company set name = '小米科技有限责任公司' where company_id = 1");
int i = 3/0;
System.out.println(index);
//提交事务
connection.commit();
} catch (Exception e) {
e.printStackTrace();
try {
//回滚事务
connection.rollback();
} catch (SQLException e1) {
}
} finally {
JdbcUtil1.closeConnection(statement, connection);
}
}
数据库连接池
- 概念:其实就是一个容器集合,存放数据库连接的容器。当系统初始化好,容器被创建,容器会申请一些连接对象,当用户来访问数据库时,从容器中获取数据库连接对象,用户访问完之后,会将连接对象归还给容器。
- 好处:节约资源;用户访问效率高
- 实现:
标准接口:
DataSource javax.sql包下的
方法:获取连接getConnection()
归还连接如果是从Connection池中获得的Connection,用Connection.close(),则归还连接,而不是释放
一般我们不需要实现它:
C3P0:数据库连接池技术
Druid:数据库连接池技术,阿里巴巴实现
1.导入jar包(两个): c3p0-0.9.5.2.jar mchange-commons-java-0.2.12.jar mysql驱动包也得导入
2.定义配置文件:c3p0.properties or c3p0-config.xml
3.创建核心对象 数据库连接对象 ComboPooledDataSource
4.获取连接:getConnection()
--代码:
配置文件:c3p0-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<!--默认配置-->
<default-config>
<property name="initialPoolSize">10</property>
<property name="maxIdleTime">30</property>
<property name="maxPoolSize">100</property>
<property name="minPoolSize">10</property>
<property name="maxStatements">200</property>
</default-config>
<!--配置连接池mysql-->
<named-config name="mysql">
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/panda?serverTimezone=UTC</property>
<property name="user">root</property>
<property name="password">123456</property>
<property name="initialPoolSize">10</property>
<property name="maxIdleTime">30</property>
<property name="maxPoolSize">100</property>
<property name="minPoolSize">10</property>
<property name="maxStatements">200</property>
</named-config>
</c3p0-config>
工具类:C3p0Util.java
package test.jdbc;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class C3p0Util {
static ComboPooledDataSource dataSource = new ComboPooledDataSource("mysql");
public static Connection getConnection() {
try {
return dataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
public static void closeConnection(Statement statement, Connection connection, ResultSet resultSet) {
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
-测试
Connection conn = C3p0Util.getConnection();
Statement statement = conn.createStatement();
int index = statement.executeUpdate("update company set name = '小米' where company_id = 1");
System.out.println(index);
C3p0Util.closeConnection(statement, conn, null);
-- 步骤
1.导入jar包(两个): druid-1.0.9.jar mysql驱动包也得导入
2.定义配置文件:是properties形式的;可以是任意名称任意目录下
3.加载配置文件。properties
4.创建核心对象 通过工厂类获取的 DruidDataSourceFactory
5.获取连接:getConnection()
-- 定义工具类
1.定义一个类 JDBCUtils
2.提供静态代码块加载配置,初始化连接池对象
3.提供方法
1)获取连接的方法:通过连接池获取连接
2)释放资源
3)获取连接池的方法
Spring JDBC
* Spring对JDBC的简单封装。提供了一个JDBC的template对象简化开发
* 步骤
1.导入jar包
2.创建JDBCTemplate对象。依赖于数据源DataSource
- JdbcTemplate template = new JdbcTemplate(ds);
3.调用JdbcTemplate的方法完成CRUD的操作
- update():DML语句
- queryForMap():将一条结果的列名作为key,值作为value,封装成map集合
- queryForList():将多条结果的列名作为key,值作为value,封装成map集合的list
- query():
List<Student> list = template.query(sql,new BeanPropertyRowMapper<Student>(Student.class));
- queryForObject():查询结果将结果封装成对象