JDBC——Java连接关系型数据库
JDBC(Java Data Base Connection) java數據庫連接 是一種用于執行SQL語句的Java API,可以為多種關系數據庫提供統一的訪問,是由一組Java語言編寫的類和接口,JDBC提供了一種基準,以此可以構建更高級的工具和接口。
之前我們簡單講了數據庫的一些知識,我們利用驅動程序簡介管理數據庫。就是因為我們安裝好數據庫后,我們的應用程序也是不能直接使用數據庫的,必須通過響應的數據庫驅動程序,通過驅動程序去和數據庫打交道,其實也就是數據庫的廠商的JDBC接口的實現。
今天我們簡單說一下,Java連接數據庫的一些步驟。
首先加載mysql驅動
這里邊的路徑是固定的,是由mysql廠家提供的驅動去找接口。
有了驅動,找接口。
加載connection接口
getConnection后三個參數:
- 連接字符串 :jdbc:mysql://(ip地址/localhost本機):(數據庫端口號)/數據庫名稱
- 數據庫賬號
- 數據庫密碼
整體代碼如下,連接成功就會輸出:連接成功。然后我們再去查詢、更新數據。
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; //連接數據庫 public class Demo1 {public static void main(String[] args) {Connection connection = null;try {//加載mysql驅動Class.forName("com.mysql.jdbc.Driver");//加載connection接口 getConnection(連接字符串,數據庫賬號,數據庫密碼);connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/myschool","root","root");System.out.println("連接成功");} catch (ClassNotFoundException | SQLException e) {e.printStackTrace();} finally {try {//關閉連接if (null != connection)connection.close();} catch (SQLException e) {e.printStackTrace();}}} }注意:連接數據庫操作完,要關閉連接!!!
這里有個問題,我們要導入的jar包,需要自己下載,javav本身不提供。
mysql-connector-java-5.1.0-bin.jar,就是mysql提供的jar包,網上很多,自己找找。
然后我們來操作數據。
通過Connection 的 createStatement()方法 獲取Statement接口
Statement statement = connection.createStatement();定義SQL 語句
String sql = "UPDATE student SET Phone = '15229975743' WHERE StudentNo = '1010'";statement接口的executeUpdate()方法傳入操作語句,返回影響成功的行數
int row = statement.executeUpdate(sql);具體代碼如下:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement;//執行修改語句,返回成功影響行數 public class Demo3 {public static void main(String[] args) {Connection connection = null;Statement statement = null;try {Class.forName("com.mysql.jdbc.Driver");connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/myschool","root","root");System.out.println("連接成功");statement = connection.createStatement();String sql = "UPDATE student SET Phone = '15229975743' WHERE StudentNo = '1010'";int row = statement.executeUpdate(sql);System.out.println(row != 0?"修改成功":"修改失敗");} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();} finally {try {if (statement != null){statement.close();}if (connection != null ){connection.close();}} catch (SQLException e) {e.printStackTrace();}}} }注意: 還是一樣的,用完即關。而且是正著用倒著關,這很好理解。
然后是查詢語句,查詢語句不一樣的是用的statement接口的executeQuery()方法,照樣傳入查詢語句,但是返回的是一個結果集合ResultSet。
ResultSet rs = statement.executeQuery(sql);這個集合同樣的在最后用完要關掉。
這里我們說一下,查詢和更新是都要傳入sql語句,而有的人會利用這個去注入惡意代碼,常見的sql注入,使得躲避掉數據庫操作權限限制。
最簡單的舉個例子,我們要求用戶名密碼都一致,才能查詢自己的成績,sql語句:
我并不知道李四的密碼,甚至不知道李四的用戶名,那我要查詢這個數據庫的信息,怎么辦,我想了個辦法,輸入這個句子:
select * from student WHERE studentUser = '' or 1=1 -- 'AND loginPwd = ''我們可以看到,我利用(’ or 1=1 – )構造了一個1=1的永真條件,后邊直接被注釋掉,那數據庫那邊收到這樣的語句條件判斷肯定為真,那我前邊要查的肯定也可以查到。
那么,mysql廠商肯定也注意到這種情況,所以為connection接口提供了prepareStatement()方法。
之前我們要先利用connection接口的createStatement()方法獲取statement接口,然后定義sql語句,在查詢或者更新數據時用statement接口的executeQuery(sql)或executeUpdate(sql)方法去傳入sql語句,進行操作,有被sql注入的風險。
現在我們利用connection接口的prepareStatement()方法去獲取preparedStatement接口,它和statement接口有相同的功能,但是會預編譯,而且prepareStatement()方法強制先傳入sql語句進行預編譯。
String sql = "select * from student WHERE studentNo = ? AND loginPwd = ?"; PreparedStatement preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1,"1010"); preparedStatement.setString(2,"123456");這里我們傳入的sql語句中先不傳值,而是用英文的?代替,叫做占位符,
在下邊用preparedStatement的(set+數據類型)方法去給占位符賦值,先說明第幾個占位符,再寫值為多少。
他就會利用預編譯將幾個值分別去驗證,而不是將整個語句打包去執行。
上面我們講了用java連接mysql數據庫后進行查詢、更新數據的方法,但是用著不是很方便,而且我們Java講究數據作為對象去使用。我們只是查到數據、更新數據,而沒有把它弄成一個對象去操作他,沒什么意義。所以,我寫了下面的工具類,可以查數據、更新數據、把數據封裝為一個類,然后去操作他。
import org.apache.commons.beanutils.BeanUtils; import java.lang.reflect.InvocationTargetException; import java.sql.*; import java.util.ArrayList; import java.util.List;public class BaseDao {private static Connection connection = null;private static PreparedStatement preparedStatement = null;private static ResultSet resultSet = null;static {try {Class.forName("com.mysql.jdbc.Driver");} catch (ClassNotFoundException e) {e.printStackTrace();}}public static void getConnection() throws SQLException {connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/myschool", "root", "root");}public static int executeUpdate(Object[] objects, String sql) {int row = 0;try {getConnection();connection.setAutoCommit(false);preparedStatement = connection.prepareStatement(sql);if (objects != null) {for (int i = 0; i < objects.length; i++) {preparedStatement.setObject(i + 1, objects[i]);}}row = preparedStatement.executeUpdate();} catch (SQLException e) {e.printStackTrace();try {connection.rollback();} catch (SQLException ex) {ex.printStackTrace();}} finally {try {connection.commit();connection.setAutoCommit(true);} catch (SQLException e) {e.printStackTrace();}closeAll();}return row;}public static ResultSet executeQuery(Object[] objects,String sql){try {getConnection();preparedStatement = connection.prepareStatement(sql);if (null != objects){for (int i = 0; i < objects.length; i++) {preparedStatement.setObject(i+1,objects[i]);}}resultSet = preparedStatement.executeQuery();} catch (SQLException e) {e.printStackTrace();}return resultSet;}public static <T> List<T> executeQuery2(Object[] objects,String sql,Class<T> tClass){List<T> list = new ArrayList<>();try {getConnection();preparedStatement = connection.prepareStatement(sql);if (null != objects){for (int i = 0; i < objects.length; i++) {preparedStatement.setObject(i+1,objects[i]);}}resultSet = preparedStatement.executeQuery();//創建集合 獲取此 ResultSet 對象的列的編號、類型和屬性。// 返回:此 ResultSet 對象的列的描述ResultSetMetaData metaData = resultSet.getMetaData();while (resultSet.next()){T obj = tClass.newInstance();for (int i = 0; i < metaData.getColumnCount(); i++) {// 獲取列名 根據下標(從1開始)String colName = metaData.getColumnName(i+1);// 根據列名 獲取 值Object value = resultSet.getObject(colName);//利用BeanUtils工具欄,創建對象BeanUtils.setProperty(obj,colName,value);}//將組裝后的結果 保存到list中list.add(obj);}} catch (SQLException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();} finally {closeAll();}return list;}public static void closeAll() {try {if(null != resultSet)resultSet.close();if(null != preparedStatement)preparedStatement.close();if(null != connection)connection.close();} catch (SQLException throwables) {throwables.printStackTrace();}} }我們利用數據庫中的屬性名、值去包裝類主要是利用BeanUtils工具類,他也需要導jar包。commons-beanutils-1.9.3 jar
再來一個測試類測一下工具是否好用:
import org.westos.demo.BaseDao; import org.westos.entity.Student; import java.util.List;public class Test {public static void main(String[] args) {String sql = "select * from student WHERE studentNo = ? AND loginPwd = ? ";Object[] objects = {1011,"123456"};List<Student> studentList = BaseDao.executeQuery2(objects,sql,Student.class);for (Student student : studentList) {System.out.println(student.getStudentname());}} }我們可以看到,有了工具類后,我們只需要輸入sql語句以及條件值就可以,他會創建好對象給我們,我們有一個集合去收就可以。再取數據用就可以后用我們java熟悉的get/set方法就ok。
我之前遇到包裝對象出錯問題,你要先確定你的屬性名、數據類型和你的數據庫中是一致的,然后還是出錯可能因為beanutils1.9.3的包太高級,利用Fasthashmap創建對象,有的Java版本低可能會失敗,所以需要找1.8的beanutils包就可以了。
好了,本次分享就到這里,希望對你有幫助,有問題請批評指正,謝謝!
總結
以上是生活随笔為你收集整理的JDBC——Java连接关系型数据库的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JAVA_出神入化学习路线大纲
- 下一篇: flutter 几秒前, 几分钟前, 几