JDBC , 使用java來控制mysql。JavaWeb開發的分層設計-三層架:DAO層設計,鏈接池使用,類加載使用,配置

 你們能夠關注一下個人博客  個人博客全部隨筆都是我從基礎開始學習java的全部知識點

1. Jdbc概述

問題:實際開發中,不可能用工具或者命令行操做數據庫,數據庫表中的數據最終要使用Java程序來操做,那麼Java中如何操做數據庫中的數據呢?java

 

Java語言中,有一個專門鏈接數據庫的規範(JDBC),專門負責鏈接數據庫進行數據操做的規範mysql

 

JDBC只是SUN編寫的一堆接口(規範的體現),SUN公司本身並無實現sql

 

 

問題 爲何SUN只定義一個JDBC規範,而不實現呢?數據庫

 

由於市面上的數據庫不少,每一個數據庫內部接口不會向外暴露,並且即使是暴露讓SUN去實現,市面上不少數據庫所有要SUN來實現不現實api

 

實際中哪一個數據庫須要支持JAVA語言,就須要本身實現JavaJDBC規範,由於實現了JDBC不少接口,那麼就會有不少實現類,而不少實現類在java中會使用一個專門的包封裝起來,叫作jar(在JDBC中叫作驅動包),各大數據庫產商實現JDBC規範之後都會把他們jar包放在官網上以供開發者下載使用瀏覽器

 

 

 

JDBC:(Java DataBase Connectivity):數據結構

是一種用於執行SQL語句的Java API,能夠爲多種關係數據庫提供統一訪問,它由一組用Java語言編寫的類和接口組成。架構

JDBC規範對應的apioracle

 

 

 

案例使用JDBC操做MySQL數據庫:框架

1. 建立普通java項目

 

2. 在項目下面新建一個lib目錄(new鍵--》folder)

 

3. MySQL驅動包拷貝到項目中並添加依賴(build path--》add to build path)

 

 

4. 開始寫代碼

DDL建立表:

package jdbc; //鏈接使用oracle數據庫


import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement; import org.junit.Test; public class Test01 { /** * Java中單元測試方法的 建立 * * 在空白處 寫 test,使用快捷鍵 alt+/ 提示,選擇 junit4 * 會自動補全 junit4單元測試的方法 * 在方法上面有一個註解,默認報錯的 * 由於:單元測試是一個框架,默認eclipse以及集成了,用戶把鼠標放置在 註解上面,按提示導入junit4 依賴便可 * 單元測試方法和main方法區別 * junit單元測試方法在一個類中能夠有多個方法,每一個一個方法能夠獨立運行 * main 主方法一個類中只能有一個方法,不太方便多個功能的測試 * * 單元測試方法的運行,光標放置在單元測試方法上面,點擊數據右鍵 【run as ->junit test】 * 綠條:表示成功 * 紅條:表示程序可能異常 */ @Test public void testName1() throws Exception { //建立表操做:要執行的sql代碼
    String sql="create table t_student(sid number(4) constraint pk_sid primary key,name varchar2(20))"; //1,加載註冊驅動
    Class.forName("oracle.jdbc.OracleDriver"); /*加載註冊驅動.(mysql的) 就是把驅動中的Driver字節碼加載到JVM中. Class.forName("com.mysql.jdbc.Driver"); 爲何這句話就能夠加載註冊驅動? 第一步:把com.mysql.jdbc.Driver.class這份字節碼加載到JVM中. 第二步:當一份字節碼被加載進JVM,立刻就會執行該字節碼中的靜態代碼塊. 第三步:該靜態代碼中,就在完成,先建立驅動對象,再註冊. * */    

    //2,獲取數據庫鏈接("jdbc:oracle:thin:@127.0.0.1:1521:數據庫名","帳號","密碼")
    Connection conn= DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl","scott","tiger"); /*jdbc:mysql://localhost:3306/dbName jdbc:mysql:// :鏈接MySQL數據庫的協議,不一樣數據庫協議不同 localhost:3306 :數據庫軟件的主機和端口 dbName : 具體要鏈接數據庫 驗證已經獲取鏈接:能夠在MySQL控制檯,使用命令:show processlist; 查看MySQL運行進程. * */
    
    //3,建立語句對象(用於執行SQL語句的對象)
    Statement c = conn.createStatement(); //4, 執行SQL語句
 c.executeUpdate(sql); //5,釋放資源(先開後關)
 c.close(); conn.close(); } }

 

package jdbc; //鏈接使用mysql數據庫



import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement; import org.junit.Test; public class Test02 { @Test public void testName1() throws Exception { //建立一個學生表 //建立表的mysql操做:要執行的sql代碼 
    String sql="create table t_student(id int primary key auto_increment,name varchar(50),age int)"; //1.加載註冊驅動
    Class.forName("com.mysql.jdbc.Driver"); //2.獲取數據庫鏈接對象
    Connection conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/lin01", "root", "root"); //3.建立語句對象(用於執行SQL語句)
    Statement st=conn.createStatement(); //4.執行SQL語句
 st.executeUpdate(sql); //5.釋放資源(先開後關)
 st.close(); conn.close(); } }

DML:表的增刪改:

package jdbc; //鏈接使用mysql數據庫



import static org.junit.Assert.*; import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement; import org.junit.Test; public class Test02 { @Test public void testName1() throws Exception { //DML 增: //建立表的mysql操做:要執行的sql代碼 
    String sql=("insert into t_student(name,age) values ('張三',20)"); //1.加載註冊驅動
    Class.forName("com.mysql.jdbc.Driver"); //2.獲取數據庫鏈接對象
    Connection conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/lin01", "root", "root"); //3.建立語句對象(用於執行SQL語句)
    Statement st=conn.createStatement(); //4.執行SQL語句
 st.executeUpdate(sql); //5.釋放資源(先開後關)
 st.close(); conn.close(); } public void testName2() throws Exception{ //DML 刪:
 String sql=("delete from t_student where id=2"); Class.forName("com.mysql.jdbc.Driver"); Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/lin01", "root", "root"); Statement st=conn.createStatement(); st.executeUpdate(sql); st.close(); conn.close(); } @Test public void testName3() throws Exception { //DML 改:
    String st="update t_student set name='李四',age=15 where id=1"; Class.forName("com.mysql.jdbc.Driver"); Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/lin01", "root", "root"); Statement cr= conn.createStatement(); cr.executeUpdate(st); cr.close(); conn.close(); } } 

 

DQL表的查詢:

package jdbc; //學生類
public class Student { private int id ; private String name; private Integer age; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Student(int id, String name, Integer age) { super(); this.id = id; this.name = name; this.age = age; } public Student() { super(); } @Override public String toString() { return "Student [id=" + id + ", name=" + name + ", age=" + age + "]"; } }

 

package jdbc; //鏈接使用mysql數據庫



import static org.junit.Assert.*; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; import java.util.ArrayList; import java.util.List; import org.junit.Test; public class Test02 { @Test public void testName1() throws Exception { //多行查詢
    String str="select * from t_student"; Class.forName("com.mysql.jdbc.Driver"); Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/lin01", "root", "root"); Statement cr = conn.createStatement(); ResultSet ex = cr.executeQuery(str); //建立一個學生類 //申明一個list集合,封裝一個個學生對象
    List<Student> stu = new ArrayList<Student>(); while(ex.next()){ //1.經過列的位置獲取對應的數據 從1開始(若是不知道類型就用Object)
        Object id = ex.getObject(1); Object name = ex.getObject(2); Object age = ex.getObject(3); System.out.println(id+"\t"+name+"\t"+age); cr.close(); conn.close(); //2.經過列的名稱獲取對應的數據((知道類型就用相應的類型)
        int id1 = ex.getInt("id"); String name1 = ex.getString("name"); int age1 = ex.getInt("age"); System.out.println(id1+"\t"+name1+"\t"+age1); cr.close(); conn.close(); //3.將每一行數據封裝成一個個Student對象
        ////快速生成變量,光標放在 代碼末尾, ctrl+1 提示
        int id2 = ex.getInt("id"); String name2 = ex.getString("name"); int age2 = ex.getInt("age"); Student student = new Student(id2,name2,age2); stu.add(student); } for (Student student : stu){ System.out.println(student); } ex.close(); cr.close(); conn.close(); } } 
package jdbc; //鏈接使用mysql數據庫



import static org.junit.Assert.*; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; import java.util.ArrayList; import java.util.List; import org.junit.Test; public class Test02 { @Test public void testName1() throws Exception { //單行查詢
    String str="select * from t_student where id=7"; Class.forName("com.mysql.jdbc.Driver"); Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/lin01", "root", "root"); Statement cr = conn.createStatement(); ResultSet ex = cr.executeQuery(str); List<Student> stu=new ArrayList<Student>(); if(ex.next()){ int id = ex.getInt("id"); String name = ex.getString("name"); int age = ex.getInt("age"); Student stud=new Student(id,name,age); stu.add(stud); } System.out.println(stu); } } 

 

 

預編譯語句對象PreparedStatment

問題 咱們有了Statment對象能夠執行SQL,爲何還要使用PreparedStatment

 

優點

  1. SQL語句結構清晰,參數的設置和SQL語句分離
  2. 性能更高
  3. 防止SQL注入

Statement: 表示靜態SQL語句對象.

PreparedStatement:Statement的子接口,表示預編譯SQL語句對象. 經過佔位符(?)來拼SQL. 

 

 

package jdbc; //鏈接使用mysql數據庫


import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import org.junit.Test; public class Test02 { @Test public void testName1() throws Exception { //使用預編譯語句對象執行DML操做 //模板sql語句(增長數據)
    String sql="insert into t_student(name,age) values(?,?) "; /**刪除:String sql = "delete from t_student where id = ?"; * 修改:String sql = "update t_student set name = ?,age=? where id = ?"; */
    // 1.加載註冊驅動
    Class.forName("com.mysql.jdbc.Driver"); // 2.獲取數據庫鏈接對象
    Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/lin01", "root", "root"); // 3.建立預編譯語句對象
    PreparedStatement pr = conn.prepareStatement(sql); //3.1設置預編譯語句對象佔位符對應的參數值
    pr.setString(1, "maxysh"); pr.setInt(2, 99); // 4.執行SQL語句 (注意:方法不能帶sql參數)
 pr.executeUpdate(); // 5.釋放資源
 pr.close(); conn.close(); } } 

 

 

package jdbc; //鏈接使用mysql數據庫


import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.ArrayList; import java.util.List; import org.junit.Test; public class Test02 { @Test public void testName1() throws Exception { //使用預編譯語句對象執行DML操做 //模板sql語句(查詢數據)
    String sql="select * from t_student "; // 1.加載註冊驅動
    Class.forName("com.mysql.jdbc.Driver"); // 2.獲取數據庫鏈接對象
    Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/lin01", "root", "root"); // 3.建立預編譯語句對象
    PreparedStatement pr = conn.prepareStatement(sql); // 4.執行SQL語句 (注意:方法不能帶sql參數)
    ResultSet ex = pr.executeQuery(); //申明一個list集合,封裝一個個學生對象
          List<Student> students = new ArrayList<Student>(); while(ex.next()){ int id = ex.getInt("id"); String name = ex.getString("name"); int age = ex.getInt("age"); Student stu=new Student(id,name,age); students.add(stu); } System.out.println(students); // 5.釋放資源
 ex.close(); pr.close(); conn.close(); } } 

 

 

 JavaWeb開發的分層設計-三層架構

 DAO層設計

 

實際開發中,JavaWeb開發代碼通常分爲三層,分層結構是JavaWeb開發中的一種設計思想,這樣會讓咱們開發井井有條,每一層只要完成對應的功能便可,使得項目便於開發和維護

 

1 . Web/表現層 : 主要接受前臺瀏覽器用戶的參數,給瀏覽器響應數據等等

2.Service/業務成/服務層:主要處理業務功能,日誌,權限,事物,等等

3.DAO/持久層 :專門負責和數據庫交互,數據處理相關代碼

 

DAO Data Access Object 數據訪問對象

 

實際開發中 用戶請求到-Web--->Service-->DAO

 

 使用DAO之後代碼的以及包的設計結構

 

開發中若是使用的分層,編寫的包和類名接口名等等都是有固定規則,不能隨便瞎寫

 

 DAO層接口包命名

 

公司域名倒寫+項目名稱/模塊名稱+dao      cn.sxt.crm.dao

 DAO層實現類包命名

 

公司域名倒寫+項目名稱/模塊名稱+dao+impl   cn.sxt.crm.dao.impl

 DAO層操做對應表的接口命名

對應表的名稱 + Dao/DAO  StudentDao/DAO , TeacherDao/DAO

DAO層操做對應表的實現類命名

 

對應表的名稱 + Dao/DAOImpl    StudentDaoImpl/DAOImpl , TeacherDaoImpl/DAOImpl

 數據表對應的Javadomain/pojo包命名

 

POJOPlain Ordinary Java Object)簡單的Java對象
domian : 域對象

 

公司域名倒寫+項目名稱/模塊名稱+domain/pojo    cn.sxt.crm.domain

對應的測試包命名

公司域名倒寫+項目名稱/模塊名稱+test     cn.sxt.crm.test

項目的工具類包命名

公司域名倒寫+項目名稱/模塊名稱+util/utils    cn.sxt.crm.util/utils

 

package cn.sxt.crm.test; import java.io.InputStream; import java.util.Properties; import org.junit.Test; /*new --->file * ClassLoader 類加載器 * ClassLoader :能夠從項目的類路徑下面讀取對應的配置文件返回一個輸入流 * ClassLoader 在程序運行的時候JVM已經爲每個項目都建立了一個,咱們開發者只須要獲取便可 * 獲取類加載器方式 * 一、使用當前線程 * ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); * 二、經過某一類的字節碼實例也能夠獲取 * ClassLoader classLoader = PropertiesTest.class.getClassLoader(); */
//ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); //使用類加載器獲取項目 類路徑下面的文件 //InputStream inputStream = classLoader.getResourceAsStream("db.properties");


/* * Properties 是Map集合下面的一個 專門用於讀取配置文件的對象 * 能夠讀取當前類路徑下面的 xxx.properites類型的配置文件 * * xxx.properites的內容必須是key=value 鍵值對的數據 */

public class PropertiesTest { @Test public void test1() throws Exception { //1.使用當前線程能夠獲取類加載器
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); //2.使用類加載器讀取db.properties配置文件
        InputStream in = classLoader.getResourceAsStream("dp.properties"); //3.建立Properties對象(專門讀取xxx.properties配置文件中的內容,本質就是Map集合,數據結構key--->value)
    Properties p = new Properties(); //4.加載配置文件
 p.load(in); System.out.println(p); //5.獲取單個指定key的值
    String str1=p.getProperty("str1"); String str2=p.getProperty("str2"); String str3=p.getProperty("str3"); String str4=p.getProperty("str4"); System.out.println(str1); } }

 

package cn.sxt.crm.test; import static org.junit.Assert.*; import java.io.InputStream; import java.sql.Connection; import java.util.Properties; import javax.sql.DataSource; import org.junit.Test; import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.pool.DruidDataSourceFactory; //Druid鏈接池的使用
public class DateSourceTest { @Test//直接手動建立鏈接池對象
public void testName1() throws Exception { //1.建立druid鏈接池對象
    DruidDataSource ds = new DruidDataSource(); ds.setDriverClassName("com.mysql.jdbc.Driver"); ds.setUrl("jdbc:mysql://localhost:3306/lin01"); ds.setUsername("root"); ds.setPassword("root"); //設置最大鏈接數
    ds.setMaxActive(10); Connection conn = ds.getConnection(); System.out.println(conn); } //使用Druid工廠對象讀取配置文件來建立鏈接池對象
@Test public void testName() throws Exception { //獲取類加載器
    ClassLoader classLoader=Thread.currentThread().getContextClassLoader(); InputStream in=classLoader.getResourceAsStream("dp.properties"); Properties properties=new Properties(); properties.load(in); //使用工廠建立鏈接池對象
    DataSource ds=DruidDataSourceFactory.createDataSource(properties ); Connection conn = ds.getConnection(); System.out.println(conn); } }
str1=com.mysql.jdbc.Driver str2=jdbc:mysql://localhost:3306/lin01
str3=root str4=root maxActive=10

-----------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------------

package cn.sxt.crm.dao; import java.util.List; import cn.sxt.crm.pojo.Student; public interface StudentDao { /** * 插入方法 * @param stu 封裝有學生信息的Student對象(數據庫自增id,開發者不須要傳id) * @return 受影響的行數 */
int insert(Student stu);//增方法

/** * 根據主鍵刪除數據 * @param id 主鍵id的值 * @return 受影響的行數 */
int delete(Integer id); /** * 修改操做 * @param stu 帶有id值的Student對象(修改根據主鍵id值修改) * @return 受影響的行數 */

int update(Student stu); /** * 單行查詢 * @param id 主鍵id * @return 單行數據封裝的對象 */ Student selectByPrimaryKey(Integer id); /** * 多行查詢 * @return 封裝有一個個Student對象的集合 */ List<Student> selectList(); }
package cn.sxt.crm.dao.impl; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.ArrayList; import java.util.List; import cn.sxt.crm.dao.StudentDao; import cn.sxt.crm.pojo.Student; import cn.sxt.crm.util.utils; public class StudentDaoImpl implements StudentDao { @Override public int insert(Student stu) { String sql="insert into t_student(name,age)values(?,?)"; Connection conn=null; PreparedStatement pr=null; try { conn =utils.getConnection(); pr = conn.prepareStatement(sql); pr.setString(1,stu.getName()); pr.setInt(2, stu.getAge()); int row=pr.executeUpdate(); return row; } catch (Exception e) { e.printStackTrace(); }finally{ utils.close(conn, pr, null); } return 0; } @Override public int delete(Integer id) { String sql="delete from t_student where id=?"; Connection conn=null; PreparedStatement pr=null; try { conn = utils.getConnection(); pr = conn.prepareStatement(sql); pr.setInt(1,id); int row=pr.executeUpdate(); return row; } catch (Exception e) { e.printStackTrace(); }finally{ utils.close(conn, pr, null); } return 0; } @Override public int update(Student stu) { String sql="update t_student set name=?,age=? where id=?"; Connection conn=null; PreparedStatement pr=null; try { conn =utils.getConnection(); pr = conn.prepareStatement(sql); pr.setString(1,stu.getName()); pr.setInt(2, stu.getAge()); pr.setInt(3, stu.getId()); int row=pr.executeUpdate(); return row; } catch (Exception e) { e.printStackTrace(); }finally{ utils.close(conn, pr, null); } return 0; } @Override public Student selectByPrimaryKey(Integer id) { String sql="select * from t_student where id=?"; Connection conn=null; PreparedStatement pr=null; ResultSet ex=null; try { conn = utils.getConnection(); pr = conn.prepareStatement(sql); pr.setInt(1,id); ex = pr.executeQuery(); while(ex.next()){ String name=ex.getString("name"); int age=ex.getInt("age"); // 封裝Student對象
                Student stu = new Student(id, name, age); //返回Student對象
                return stu; } } catch (Exception e) { e.printStackTrace(); }finally{ utils.close(conn, pr, ex); } return null; } @Override public List<Student> selectList() { List<Student> student= new ArrayList<Student>(); String sql="select * from t_student"; Connection conn=null; PreparedStatement pr=null; ResultSet ex=null; try { conn =utils.getConnection(); pr = conn.prepareStatement(sql); ex = pr.executeQuery(); while(ex.next()){ int id=ex.getInt("id"); String name=ex.getString("name"); int age=ex.getInt("age"); // 封裝Student對象
                Student stu = new Student(id, name, age); // 學生對象添加到集合中
 student.add(stu); } } catch (Exception e) { e.printStackTrace(); }finally{ utils.close(conn, pr, ex); } return student; } }
package cn.sxt.crm.pojo; public class Student { private Integer id; private String name; private Integer age; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Student(Integer id, String name, Integer age) { super(); this.id = id; this.name = name; this.age = age; } public Student() { super(); } @Override public String toString() { return "Student [id=" + id + ", name=" + name + ", age=" + age + "]"; } }
package cn.sxt.crm.test; import java.util.List; import org.junit.Test; import cn.sxt.crm.dao.StudentDao; import cn.sxt.crm.dao.impl.StudentDaoImpl; import cn.sxt.crm.pojo.Student; public class StudentDaoTest { private StudentDao dao=new StudentDaoImpl(); @Test public void testInsert() { Student stu=new Student(null, "葉孤城", 30); int row=dao.insert(stu); System.out.println(row); } @Test public void testDelete() { int row=dao.delete(10); System.out.println(row); } @Test public void testUpdate() { Student stu=new Student(9, "葉孤城", 30); int row=dao.update(stu); System.out.println(row); } @Test public void testSelectByPrimaryKey() { Student stu = dao.selectByPrimaryKey(3); System.out.println(stu); } @Test public void testSelectList() { List<Student> students = dao.selectList(); System.out.println(students); } }
package cn.sxt.crm.util; import java.io.InputStream; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Properties; import javax.sql.DataSource; import com.alibaba.druid.pool.DruidDataSourceFactory; public class utils { // 建立讀取配置文件的配置對象
        private static Properties p=new Properties(); //鏈接池對象
        private static DataSource da; static { try { ClassLoader classLoader=Thread.currentThread().getContextClassLoader(); InputStream inputStream=classLoader.getResourceAsStream("dp.properties"); p.load(inputStream); //建立鏈接池對象
                da= DruidDataSourceFactory.createDataSource(p); } catch (Exception e) { e.printStackTrace(); } } public static Connection getConnection(){ try { Connection conn = da.getConnection(); return conn; } catch (Exception e) { throw new RuntimeException("鏈接失敗"); } } public static void close(Connection conn,PreparedStatement pr,ResultSet ex){ try { if(ex!=null){ex.close();} } catch (SQLException e1) { e1.printStackTrace(); }finally{ try { if(pr!=null){ pr.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ try { if(conn!=null){ conn.close(); } } catch (SQLException e) { e.printStackTrace(); } }} } }

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/lin01
username=root
password=root
maxActive=1

配置必須按規定命名,

相關文章
相關標籤/搜索