连接
- 加载驱动。
- 获取连接(此时需要提供数据库连接的账号、密码、url)。
- 编写sql语句。
- 创建sql编译器。
- 执行sql语句并返回结果集。
- 解析结果集(只有查询操作才有,增删改返回的是受影响的行数)。
代码:
public class JdbcDemo {
public static void main(String[] args) throws SQLException {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
// 1.加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 2.获取连接
final String user = "root";
final String pwd = "root";
// final String url = "jdbc:mysql://localhost:3306/offcna?serverTimezone=GMT%2B8&characterEncoding=utf-8";
// 如果是本地的数据库,并且端口为3306,可以下面这样写
final String url = "jdbc:mysql:///offcna?serverTimezone=GMT%2B8&characterEncoding=utf-8";
conn = DriverManager.getConnection(url, user, pwd);
// 3.编写sql
String sql = "select * from offcna.emp";
// 4.创建sql编译器
stmt = conn.createStatement();
// 5.执行sql并返回结果集
rs = stmt.executeQuery(sql);
// 6.解析结果集
while (rs.next()) {
String ename = rs.getString("ename");
System.out.println(ename);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
conn.close();
stmt.close();
rs.close();
}
}
}
prepareStatement 防止sql注入
PreparedStatement可对SQL进行预编译,从而提高数据库的执行效率。并且PreperedStatement对于
sql中的参数,允许使用占位符的形式进行替换,简化sql语句的编写。
例:
public class PStmtDemo {
// 根据用户给的员工姓名查询员工信息
public void getEmpByEname(String ename) {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
final String user = "root";
final String pwd = "root";
final String url = "jdbc:mysql:///offcna?serverTimezone=GMT%2B8&characterEncoding=utf-8";
conn = DriverManager.getConnection(url, user, pwd);
String sql = "select * from offcna.emp where ename = ?";
pstmt = conn.prepareStatement(sql); //创建PreparedStatement对象时会对sql进行预编译
pstmt.setString(1, ename);
System.out.println(pstmt.toString());
rs = pstmt.executeQuery();
while (rs.next()) {
System.out.println(rs.getString("ename") + " , ");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (rs != null) {
conn.close();
}
if (pstmt != null) {
pstmt.close();
}
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
@Test
public void test() {
String ename = "'ALLEN' or 1=1 #";
String ename1 = "ALLEN";
getEmpByEname(ename);
System.out.println("\'");
}
}
c3p0连接池
- 导jar包、写配置文件
- 写工具类
工具类代码:
public class C3p0Util {
// 初始化连接池 (通过配置文件自动初始化)
private static ComboPooledDataSource ds = new ComboPooledDataSource();
private static ThreadLocal<Connection> t = new ThreadLocal<>();
/**
* 创建获取连接的方法
*
* @return
*/
public static Connection getConn() {
Connection conn = null;
try {
if ((conn = t.get()) == null) {
conn = ds.getConnection();
t.set(conn);
}
return ds.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
/**
* 创建归还连接的方法
*
* @param conn
* @param pstmt
* @param rs
*/
public static void returnConn(Connection conn, PreparedStatement pstmt, ResultSet rs) {
try {
if (rs != null) {
rs.close();
}
if (pstmt != null) {
pstmt.close();
}
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Druid
- 导入jar包
- 读取配置文件,但是druid读取配置文件需要获得文件的输入流。
public class DruidUtil {
private static DataSource ds = null;
// 初始化连接池
static {
// 1.获取配置文件输入流,因为是在项目根目录下,所以可以用此方法进行获取
InputStream in = DruidUtil.class.getClassLoader().getResourceAsStream("druid.properties");
Properties prop = new Properties();
try {
// 2. 读取配置文件
prop.load(in);
// 3. 根据配置文件获取输入流
ds = DruidDataSourceFactory.createDataSource(prop);
} catch (Exception e) {
e.printStackTrace();
}
}
// 创建获取连接的方法
public static Connection getConn() {
try {
return ds.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
// 创建归还连接的方法
public static void returnConn(Connection conn, PreparedStatement pstmt, ResultSet rs) {
try {
if (rs != null) {
rs.close();
}
if (pstmt != null) {
pstmt.close();
}
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Commons.DBUtils包
Commons DbUtils的核心是两个类一个接口:
- DBUtils类:主要为关闭连接,装载JDBC驱动程序之类的常规工作提供方法,都是静态的方法。
- QueryRunner类:为我们提供两个重要方法,调用方法之前需要先创建一个QueryRunner的对象.
创建示例:
// 根据c3p0的数据源获得 查询运行器
private QueryRunner qr = new QueryRunner(new ComboPooledDataSource());
创建对象时需要传入一个连接池的数据源,这里结合c3p0连接池来完成。
一个查询示例:
public List<Account> getAll() {
List<Account> accountList = null;
QueryRunner qr = new QueryRunner(new ComboPooledDataSource());
try {
String sql = "select * from account";
// 将查询的数据用指定的类型进行封装(第二个参数),由于结果集的类型不,query()方法返回的类型也不同,此处返回的是List集合
accountList = qr.query(sql, new BeanListHandler<>(Account.class));
} catch (Exception e) {
e.printStackTrace();
}
return accountList;
}
对于返回的结果集:
- ResultSetHandler接口:用于处理ResultSet结果集,将结果集的的数据转换成不同形式。该接口的实现类有很多:
ArrayHandler | 将结果集中的第一条记录封装到一个Object[]数组中,数组中的每一个元素就是这条记录中的每一个字段的值。 |
---|---|
ArrayListHandler | 将结果集中的每一条记录都封装到一个Object[]数组中,将这些数组在封装到List集合中。 |
BeanHandler | 将结果集中第一条记录封装到一个指定的javaBean中。 |
BeanListHandler | 将结果集中每一条记录封装到指定的javaBean中,将这些javaBean在封装到List集合中。 |
ColumnListHandler | 将结果集中指定的列的字段值,封装到一个List集合中。 |
ScalarHandler | 它是用于单个数据查询。例如:select count(*) from users 操作。 |
MapHandler | 将结果集中第一条记录封装到Map集合中,Key代表列名, Value代表该列数据。 |
MapListHandler | 将结果集中每一条记录封装到Map集合中,Key代表列名, Value代表该列数据,Map集合再存储到List集合 |