初识JDBC
一、JDBC简介
JDBC(Java Data Base Connectivity)是一种用于连接数据库的Java API
- 实现Java程序对各种数据库的访问
- 一组接口和类,位于java.sql与javax.sql包
- 面向接口编程
- JDBC步骤固定
Java应用程序连接数据库时,是通过厂商提供的驱动来加载并连接的。
二、Java连接数据库
连接数据库主要有以下几步:
-
加载驱动
Class.forName("com.mysql.jdbc.Driver");
-
DrivaerManager
获取Connectior连接
DriverManager.getConnection(url,"数据库名","数据库密码");
-
创建Statement
String sql = "SELECT id,title FROM news_detail WHERE title = '初识JDBC'; // 创建Statement用于发送命令 Statement state = connection.createStatement(); // 将sql命令发送到数据库 state.executeQuery(sql)
-
返回ResultSet
// 得到数据库响应 ResultSet rs = stmt.executeQuery(sql);
-
释放资源
Statement和preparedStatement发送命令方式
// Statement连接方式
public class TestJDBC {
public static void main(String[] args) {
Connection conn = null;
Statement statement = null;
ResultSet rs = null;
try {
// 1.使用DriverManager管理驱动
// registerDriver 注册/加载驱动
// Driver是一个接口 它需要寻找对应的实现类(数据库厂商提供的驱动类们)
Driver driver = new com.mysql.jdbc.Driver();
DriverManager.registerDriver(driver);
// 2.建立和数据库的连接 Connection
// 类似于http://192.168.12.138:8080/各级资源目录
// 数据库地址:协议://主机地址/数据库名
String url = "jdbc:mysql://127.0.0.1:3306/myschool";
// 数据库用户名
String user = "root";
// 数据库用户密码
String password = "root";
conn = DriverManager.getConnection(url, user, password);
// 3.使用Statement执行SQL语句
statement = conn.createStatement();
String sql = "select * from student";
rs = statement.executeQuery(sql);
// 4.对返回的数据结果集ResultSet进行解析
// 这个结果集可以将其看作是一个二维表
// boolean next() 移动指针 判断是否有下一行数据
while(rs.next()) {
// int getInt(int columnIndex) 根据列索引取列的数据
// int getInt(String columnLabel) 根据列名取列的数据
int id = rs.getInt(1);
String stuName = rs.getString("stuName");
String address = rs.getString("address");
System.out.println(id+" -- "+stuName+" -- "+address);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
// 5.关流
// 先开的后关
if(rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
SQL注入
public class NewsDao {
public void getNesByTitle(String title) {
Connection connection = null;
Statement stmt = null;
ResultSet rs = null;
try {
// 连接数据库
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/kgcnews";
connection = DriverManager.getConnection(url,"root","root");
/*
这里需要注意,因为这里的sql命令是通过拼接发送的;
所以也可以拼接这样的字符串
“ '初识JDBC' or '1'='1' ”这样就会将所有的数据库信息全部查到
所以不安全
*/
String sql = "SELECT id,title FROM news_detail where title="+title;
System.out.println(sql);
stmt = connection.createStatement();
rs = stmt.executeQuery(sql);
while(rs.next()) {
int id = rs.getInt("id");
String title1 = rs.getString("title");
System.out.println(id+"\t"+title1);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}finally {
try {
rs.close();
stmt.close();
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
NewsDao newsDao = new NewsDao();
newsDao.getNesByTitle("'初识JDBC' or '1'='1'");
}
}
为了解决这个问题Java提供了另一种发送命令的方式
PreparedStatemet
public class PreparedStatementTest {
/**创建连接*/
Connection connection = null;
/**创建PreparedStatement*/
PreparedStatement ps = null;
/**创建集合ResultSet*/
ResultSet rs = null;
/**获取数据库连接*/
public void getConnection() {
try {
// 反射获得驱动
Class.forName("com.mysql.jdbc.Driver");
// 获取连接
String url = "jdbc:mysql://127.0.0.1:3306/kgcnews";
connection = DriverManager.getConnection(url, "root", "root");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
public void getNewsByTitle(String title) {
try {
getConnection();
// 发出sql命令
String sql = "select id,title from news_detail where title = ?";
ps = connection.prepareStatement(sql);
// 这样可以防止SQL注入
ps.setString(1, title);
// 得到集合
rs = ps.executeQuery();
// 遍历ResultSet
while(rs.next()) {
int id = rs.getInt("id");
String newsTitle = rs.getString("title");
System.out.println(id+"\t"+newsTitle);
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
destroy();
}
}
public static void main(String[] args) {
PreparedStatementTest pst = new PreparedStatementTest();
pst.getNewsByTitle("初识JDBC");
}
Statement与PreparedStatemet区别
-
PreparedStatement接口继承Statement
-
Statement st = connection.createStatement();
-
PreparedStatement pstm = connection.prepareStatement(sql);
- SQL语句使用“?”作为数据站位符
- 使用setXXX()方法设置数据
PreparedStatement——预编译
- 效率高、性能好、开销小
- 安全性好
- 代码可读性高
三、JDBC的增删改查方法
/**增删改 修改新闻标题*/
public void updateNews(int id,String title) {
// 获得连接
getConnection();
String sql = "update news_detail set title= ? where id = ?";
try {
ps = connection.prepareStatement(sql);
ps.setString(1, title);
ps.setInt(2, id);
// 修改是ps.executeUpdate()它返回的是数据库修改的行数
if (ps.executeUpdate() > 0) {
System.out.println("修改新闻标题成功!");
}else {
System.out.println("修改新闻标题失败!");
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
destroy();
}
}
/**查询方法 查询全部的新闻*/
public void searchAllNews() {
getConnection();
String sql = "select id,categoryId,title,summary,content,author,createDate from news_detail";
try {
ps = connection.prepareStatement(sql);
// 得到查询是ps.executeQuery()它返回的是ResultSet二维表集合
rs = ps.executeQuery();
while(rs.next()) {
int id = rs.getInt("id");
int categoryId = rs.getInt("categoryId");
String title = rs.getString("title");
String summary = rs.getString("summary");
String content = rs.getString("content");
String author = rs.getString("author");
Timestamp createDate = rs.getTimestamp("createDate");
System.out.println(id+"\t"+categoryId+"\t"+title+"\t"+summary+"\t"+content+"\t"+author+"\t"+createDate);
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
destroy();
}
}
/**关闭连接方法*/
public void destroy() {
try {
if (rs != null) {
rs.close();
}
if (ps != null) {
ps.close();
}
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}