1 JDBC
1.1 JDBC的基本概念
JDBC(Java DataBase Connectivity)
是官方(sun
公司)定义的一套操作所有关系型数据库的规则,它由一组用Java
语言编写的类和接口组成,各个数据库厂商去实现这套接口,提供数据库驱动jar
包。
1.2 JDBC的基本实现
package com.hc.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBCDemo01 {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
try {
// 1.注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 2.获取数据库连接对象
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/s_t?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT", "root", "****");
// 3.定义sql语句
// String sql = "update student set Sage = 30 where Sno = '201215121'";
// String sql = "update student set Sage = 19";
String sql = "insert into student values ('201215126','黄P','男','23','CS')";
// 4.获取执行sql的对象 Statement
statement = connection.createStatement();
// 5.执行sql
int flag = statement.executeUpdate(sql);
// 6.处理结果
System.out.println(flag);
if (flag > 0) {
System.out.println("操作成功!");
} else {
System.out.println("操作失败!");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 7.释放资源
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
1.3 JDBC中的基本对象
1.3.1 DriverManager
- 注册驱动,告诉程序使用哪一个数据库驱动
jar
包。
DriverManager
类中的static void registerDriver(Driver driver)
负责注册。然而,1.2中似乎并未调用该方法,通过查看源码发现:在com.mysql.cj.jdbc.Driver
类中存在静态代码块如下:
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
可以看出,Class.forName("com.mysql.cj.jdbc.Driver");
即在进行驱动的注册,mysql 5
之后的驱动jar
包可以省略注册驱动的步骤。
- 获取数据库连接对象。
DriverManager
类中的static Connection getConnection(String url, String user, String password)
负责获取数据库的连接。参数规则如下:
url
:指定连接的路径,语法jdbc:mysql://ip地址(域名):端口号/数据库名称
,例如,jdbc:mysql://localhost:3306/s_t
。当然,如果连接的是本机mysql
服务器,并且mysql
服务默认端口是3306
,则url
可以简写为:jdbc:mysql:///数据库名称
。
user
:用户名
password
:密码
1.3.2 Connection
- 获取执行
sql
的对象。
Connection
类中存在两个执行sql
的对象,具体为Statement createStatement()
和PreparedStatement prepareStatement(String sql)
。 - 事务管理。
开启事务:setAutoCommit(boolean autoCommit)
,调用该方法设置参数为false
,即开启事务
提交事务:commit()
回滚事务:rollback()
1.3.3 Statement
Statement
执行sql
的对象:
boolean execute(String sql)
:可以执行任意的sql
int executeUpdate(String sql)
:执行DML
(insert
、update
、delete
)语句、DDL
(create
,alter
、drop
)语句。(返回值:影响的行数,可以通过这个影响的行数判断DML
语句是否执行成功,返回值 > 0的则执行成功,反之,则失败)ResultSet executeQuery(String sql)
:执行DQL
(select
)语句
1.3.4 PreparedStatement
PreparedStatement
对象是为了解决SQL
注入问题,SQL
注入问题是指在拼接sql
时,有一些sql
的特殊关键字参与字符串的拼接,会造成安全性问题,例如:sql:select * from user where username = 'fhdsjkf' and password = 'a' or 'a' = 'a'
。
解决方法:预编译的SQL:参数使用?作为占位符。例如,select * from user where username = ? and password = ?;
1.3.5 ResultSet
ResultSet
:结果集对象,封装查询结果
boolean next()
:游标向下移动一行,判断当前行是否是最后一行末尾(是否有数据),如果是,则返回false
,如果不是则返回true
getXxx(参数)
:获取数据。Xxx
:代表数据类型。例如:int getInt()
,String getString()
。
int
:代表列的编号,从1
开始,如:getString(1)
。
String
:代表列名称。 如:getDouble("balance")
。
实验步骤如下:
1. 游标向下移动一行
2. 判断是否有数据
3. 获取数据
//循环判断游标是否是最后一行末尾。
while(rs.next()){
//获取数据
int id = rs.getInt(1);
String name = rs.getString("name");
double balance = rs.getDouble(3);
System.out.println(id + "---" + name + "---" + balance);
}
2 JDBC连接池
关于连接池的概念和引入看此。
2.1 C3P0连接池
- ① 定义配置文件
c3p0-config.xml
,放置在src目录下即可
<c3p0-config>
<!-- 使用默认的配置读取连接池对象 -->
<default-config>
<!-- 连接参数 -->
<property name="driverClass">com.mysql.cj.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/s_t?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT</property>
<property name="user">root</property>
<property name="password">root</property>
<!-- 连接池参数 -->
<property name="initialPoolSize">5</property>
<property name="maxPoolSize">10</property>
<property name="checkoutTimeout">3000</property>
</default-config>
<named-config name="otherc3p0">
<!-- 连接参数 -->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/day25</property>
<property name="user">root</property>
<property name="password">root</property>
<!-- 连接池参数 -->
<property name="initialPoolSize">5</property>
<property name="maxPoolSize">8</property>
<property name="checkoutTimeout">1000</property>
</named-config>
</c3p0-config>
- ② 测试
package com.hc.datasource.c3p0;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
public class C3P0Demo {
public static void main(String[] args) throws SQLException {
// 1.创建数据库连接池对象
DataSource dataSource = new ComboPooledDataSource();
// 2. 获取连接对象,并测试其最大连接个数
for (int i = 1; i <= 11; i++) {
Connection connection = dataSource.getConnection();
System.out.println(connection);
if (i == 5)
connection.close();
}
}
}
2.2 Druid连接池
下面采取封装工具类的方式实现Druid连接池:
- ① 定义配置文件,放置
src
或其他目录都可
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/s_t?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT
username=root
password=1234
initialSize=5
maxActive=10
maxWait=3000
- ② 定义工具类
package com.hc.utils;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class JDBCUtils {
private static DataSource dataSource;
static {
try {
Properties properties = new Properties();
InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");
properties.load(is);
dataSource = DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
public static void close(Connection conn,Statement stat){
close(conn,stat,null);
}
public static void close(Connection conn, Statement stat, ResultSet resu){
if(resu != null){
try {
resu.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();
}
}
}
public static DataSource getDataSource(){
return dataSource;
}
}
- ③ 测试
package com.hc.datasource.druid;
import com.hc.utils.JDBCUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class DruidUtilsTest {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement prep = null;
try {
conn = JDBCUtils.getConnection();
String sql = "insert into student values(?,?,?,?,?)";
prep = conn.prepareStatement(sql);
prep.setString(1, "201215129");
prep.setString(2, "皇城");
prep.setString(3, "女");
prep.setInt(4, 23);
prep.setString(5, "CS");
int res = prep.executeUpdate();
System.out.println(res);
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.close(conn, prep);
}
}
}
3 Spring JDBC
Spring
框架对JDBC
进行了简单的封装,提供了一个JDBCTemplate
对象简化JDBC
的开发。代码测试如下:
package com.hc.template;
import com.hc.domain.student;
import com.hc.utils.JDBCUtils;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import java.util.List;
import java.util.Map;
public class JDBCTemplateDemo {
public static void main(String[] args) {
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
String sql = "update student set Sname = ? where Sno = ?";
int count = jdbcTemplate.update(sql, "黄世称", "201215121");
System.out.println(count);
sql = "delect from student where Sno = ?";
count = jdbcTemplate.update(sql, "201215130");
System.out.println(count);
sql = "insert into student values(?,?,?,?,?)";
count = jdbcTemplate.update(sql, "201215130", "邓世昌", "女", 25, "CS");
System.out.println(count);
sql = "select * from student where Sno = ?";
Map<String, Object> stringObjectMap = jdbcTemplate.queryForMap(sql, "201215121");
System.out.println(stringObjectMap);
sql = "select * from student";
List<Map<String, Object>> lists = jdbcTemplate.queryForList(sql);
for (Map<String, Object> map : lists) {
System.out.println(map);
}
List<student> studentList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<student>(student.class));
for (student s : studentList) {
System.out.println(s.toString());
}
}
}