如下我是概括的JDBC知識點圖:java
圖上的知識點均可以在我其餘的文章內找到相應內容。mysql
JDBC操做數據庫的步驟 ?
代碼以下:面試
Connection connection = null; Statement statement = null; ResultSet resultSet = null; try { /* * 加載驅動有兩種方式 * * 1:會致使驅動會註冊兩次,過分依賴於mysql的api,脫離的mysql的開發包,程序則沒法編譯 * 2:驅動只會加載一次,不須要依賴具體的驅動,靈活性高 * * 咱們通常都是使用第二種方式 * */ //1. //DriverManager.registerDriver(new com.mysql.jdbc.Driver()); //2. Class.forName("com.mysql.jdbc.Driver"); //獲取與數據庫鏈接的對象-Connetcion connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/zhongfucheng", "root", "root"); //獲取執行sql語句的statement對象 statement = connection.createStatement(); //執行sql語句,拿到結果集 resultSet = statement.executeQuery("SELECT * FROM users"); //遍歷結果集,獲得數據 while (resultSet.next()) { System.out.println(resultSet.getString(1)); System.out.println(resultSet.getString(2)); } } catch (SQLException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } finally { /* * 關閉資源,後調用的先關閉 * * 關閉以前,要判斷對象是否存在 * */ if (resultSet != null) { try { resultSet.close(); } catch (SQLException e) { e.printStackTrace(); } } if (statement != null) { try { statement.close(); } catch (SQLException e) { e.printStackTrace(); } } if (connection != null) { try { connection.close(); } catch (SQLException e) { e.printStackTrace(); } } }
JDBC中的Statement 和PreparedStatement的區別?
區別:sql
JDBC中大數據量的分頁解決方法?
最好的辦法是利用sql語句進行分頁,這樣每次查詢出的結果集中就只包含某頁的數據內容。數據庫
mysql語法:apache
SELECT * FROM 表名 LIMIT [START], length;
oracle語法:api
SELECT *FROM ( SELECT 列名,列名,ROWNUM rn FROM 表名 WHERE ROWNUM<=(currentPage*lineSize)) temp WHERE temp.rn>(currentPage-1)*lineSize;
說說數據庫鏈接池工做原理和實現方案?
工做原理:緩存
實現方案:鏈接池使用集合來進行裝載,返回的Connection是原始Connection的代理,代理Connection的close方法,當調用close方法時,不是真正關鏈接,而是把它代理的Connection對象放回到鏈接池中,等待下一次重複利用。tomcat
具體代碼:安全
@Override public Connection getConnection() throws SQLException { if (list.size() > 0) { final Connection connection = list.removeFirst(); //看看池的大小 System.out.println(list.size()); //返回一個動態代理對象 return (Connection) Proxy.newProxyInstance(Demo1.class.getClassLoader(), connection.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //若是不是調用close方法,就按照正常的來調用 if (!method.getName().equals("close")) { method.invoke(connection, args); } else { //進到這裏來,說明調用的是close方法 list.add(connection); //再看看池的大小 System.out.println(list.size()); } return null; } }); } return null; }
Java中如何進行事務的處理?
Connection類中提供了4個事務處理方法:
savepoint:保存點
下述程序是一段簡單的基於JDBC的數據庫訪問代碼,實現瞭如下功能:從數據庫中查詢product表中的全部記錄,而後打印輸出到控制檯.該代碼質量較低,如沒有正確處理異常,鏈接字符串以」魔數」的形式直接存在於代碼中等,請用你的思路從新編寫程序, 完成相同的功能,提升代碼質量.
原來的代碼:
public void printProducts(){ Connection c = null; Statements s = null; ResultSet r = null; try{ c=DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:sid","username","password"); s=c.createStatement(); r=s.executeQuery("select id, name, price from product"); System.out.println("Id\tName\tPrice"); while(r.next()){ int x = r.getInt("id"); String y = r.getString("name"); float z = r.getFloat("price"); System.out.println(x + "\t" + y + "\t" + z); } } catch(Exception e){ } }
修改後的代碼:
class Constant{ public static final String URL="jdbc:oracle:thin:@127.0.0.1:1521:sid"; public static final String USERNAME="username"; public static final String PASSWORD="password"; } class DAOException extends Exception{ public DAOException(){ super(); } public DAOException(String msg){ super(msg); } } public class Test{ public void printProducts() throws DAOException{ Connection c = null; Statement s = null; ResultSet r = null; try{ c = DriverManager.getConnection(Constant.URL,Constant.USERNAME,Constant.PASSWORD); s = c.createStatement(); r = s.executeQuery("select id,name,price from product"); System.out.println("Id\tName\tPrice"); while(r.next()){ int x = r.getInt("id"); String y = r.getString("name"); float z = r.getFloat("price"); System.out.println(x + "\t" + y + "\t" + z); } } catch (SQLException e){ throw new DAOException("數據庫異常"); } finally { try{ r.close(); s.close(); c.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
修改點:
寫出一段JDBC鏈接本機MySQL數據庫的代碼
Class.forName("com.mysql.jdbc.Driver"); String url="jdbc:mysql://localhost/test"; Stirng user='root'; String password='root'; Connection conn = DriverManager.getConnection(url,user,password);
JDBC是如何實現Java程序和JDBC驅動的鬆耦合的?
經過制定接口,數據庫廠商來實現。咱們只要經過接口調用便可。隨便看一個簡單的JDBC示例,你會發現全部操做都是經過JDBC接口完成的,而驅動只有在經過Class.forName反射機制來加載的時候纔會出現。
execute,executeQuery,executeUpdate的區別是什麼?
PreparedStatement的缺點是什麼,怎麼解決這個問題?
PreparedStatement的一個缺點是,咱們不能直接用它來執行in條件語句;須要執行IN條件語句的話,下面有一些解決方案:
JDBC的髒讀是什麼?哪一種數據庫隔離級別能防止髒讀?
髒讀:一個事務讀取到另一個事務未提交的數據
例子:A向B轉帳,A執行了轉帳語句,但A尚未提交事務,B讀取數據,發現本身帳戶錢變多了!B跟A說,我已經收到錢了。A回滾事務【rollback】,等B再查看帳戶的錢時,發現錢並無多。
下面的三種個隔離級別均可以防止:
什麼是幻讀,哪一種隔離級別能夠防止幻讀?
是指在一個事務內讀取到了別的事務插入的數據,致使先後讀取不一致。
只有TRANSACTION_SERIALIZABLE隔離級別才能防止產生幻讀。
JDBC的DriverManager是用來作什麼的?
JDBC的ResultSet是什麼?
有哪些不一樣的ResultSet?
根據建立Statement時輸入參數的不一樣,會對應不一樣類型的ResultSet。若是你看下Connection的方法,你會發現createStatement和prepareStatement方法重載了,以支持不一樣的ResultSet和併發類型。
一共有三種ResultSet對象。
ResultSet有兩種併發類型。
JDBC的DataSource是什麼,有什麼好處
DataSource即數據源,它是定義在javax.sql中的一個接口,跟DriverManager相比,它的功能要更強大。咱們能夠用它來建立數據庫鏈接,固然驅動的實現類會實際去完成這個工做。除了能建立鏈接外,它還提供了以下的特性:
如何經過JDBC的DataSource和Apache Tomcat的JNDI來建立鏈接池?
Tomcat服務器也給咱們提供了鏈接池,內部其實就是DBCP
步驟:
context.xml文件的配置:
<Context> <Resource name="jdbc/EmployeeDB" auth="Container" type="javax.sql.DataSource" username="root" password="root" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/zhongfucheng" maxActive="8" maxIdle="4"/> </Context>
try { //初始化JNDI容器 Context initCtx = new InitialContext(); //獲取到JNDI容器 Context envCtx = (Context) initCtx.lookup("java:comp/env"); //掃描以jdbc/EmployeeDB名字綁定在JNDI容器下的鏈接池 DataSource ds = (DataSource) envCtx.lookup("jdbc/EmployeeDB"); Connection conn = ds.getConnection(); System.out.println(conn); }
Apache的DBCP是什麼
若是用DataSource來獲取鏈接的話,一般獲取鏈接的代碼和驅動特定的DataSource是緊耦合的。另外,除了選擇DataSource的實現類,剩下的代碼基本都是同樣的。
Apache的DBCP就是用來解決這些問題的,它提供的DataSource實現成爲了應用程序和不一樣JDBC驅動間的一個抽象層。Apache的DBCP庫依賴commons-pool庫,因此要確保它們都在部署路徑下。
使用DBCP數據源的步驟:
private static DataSource dataSource = null; static { try { //讀取配置文件 InputStream inputStream = Demo3.class.getClassLoader().getResourceAsStream("dbcpconfig.properties"); Properties properties = new Properties(); properties.load(inputStream); //獲取工廠對象 BasicDataSourceFactory basicDataSourceFactory = new BasicDataSourceFactory(); dataSource = basicDataSourceFactory.createDataSource(properties); } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { return dataSource.getConnection(); } //這裏釋放資源不是把數據庫的物理鏈接釋放了,是把鏈接歸還給鏈接池【鏈接池的Connection內部本身作好了】 public static void release(Connection conn, Statement st, ResultSet rs) { if (rs != null) { try { rs.close(); } catch (Exception e) { e.printStackTrace(); } rs = null; } if (st != null) { try { st.close(); } catch (Exception e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (Exception e) { e.printStackTrace(); } } }
常見的JDBC異常有哪些?
有如下這些:
JDBC中存在哪些不一樣類型的鎖?
從廣義上講,有兩種鎖機制來防止多個用戶同時操做引發的數據損壞。
java.util.Date和java.sql.Date有什麼區別?
java.util.Date包含日期和時間,而java.sql.Date只包含日期信息,而沒有具體的時間信息。若是你想把時間信息存儲在數據庫裏,能夠考慮使用Timestamp或者DateTime字段
SQLWarning是什麼,在程序中如何獲取SQLWarning?
SQLWarning是SQLException的子類,經過Connection, Statement, Result的getWarnings方法均可以獲取到它。 SQLWarning不會中斷查詢語句的執行,只是用來提示用戶存在相關的警告信息。
若是java.sql.SQLException: No suitable driver found該怎麼辦?
若是你的SQL URL串格式不正確的話,就會拋出這樣的異常。不論是使用DriverManager仍是JNDI數據源來建立鏈接都有可能拋出這種異常。它的異常棧看起來會像下面這樣。
org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot create JDBC driver of class 'com.mysql.jdbc.Driver' for connect URL ''jdbc:mysql://localhost:3306/UserDB' at org.apache.tomcat.dbcp.dbcp.BasicDataSource.createConnectionFactory(BasicDataSource.java:1452) at org.apache.tomcat.dbcp.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:1371) at org.apache.tomcat.dbcp.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044) java.sql.SQLException: No suitable driver found for 'jdbc:mysql://localhost:3306/UserDB at java.sql.DriverManager.getConnection(DriverManager.java:604) at java.sql.DriverManager.getConnection(DriverManager.java:221) at com.journaldev.jdbc.DBConnection.getConnection(DBConnection.java:24) at com.journaldev.jdbc.DBConnectionTest.main(DBConnectionTest.java:15) Exception in thread "main" java.lang.NullPointerException at com.journaldev.jdbc.DBConnectionTest.main(DBConnectionTest.java:16)
解決這類問題的方法就是,檢查下日誌文件,像上面的這個日誌中,URL串是'jdbc:mysql://localhost:3306/UserDB,只要把它改爲jdbc:mysql://localhost:3306/UserDB就行了。
JDBC的RowSet是什麼,有哪些不一樣的RowSet?
RowSet用於存儲查詢的數據結果,和ResultSet相比,它更具靈活性。RowSet繼承自ResultSet,所以ResultSet能幹的,它們也能,而ResultSet作不到的,它們仍是能夠。RowSet接口定義在javax.sql包裏。
RowSet提供的額外的特性有:
RowSet分爲兩大類:
B. 離線型RowSet——這類對象不須要和數據庫進行鏈接,所以它們更輕量級,更容易序列化。它們適用於在網絡間傳遞數據。
有四種不一樣的離線型RowSet的實現。
什麼是JDBC的最佳實踐?
若是文章有錯的地方歡迎指正,你們互相交流。習慣在微信看技術文章的同窗, 能夠關注微信公衆號:Java3y