JDBC(3)----------service層以及三層架構的完整的JDBC實例

1、service業務層(biz(bussiness)層)

    a)業務層:業務層裏面主要封裝的是一些業務功能是由對DAO的一次到多次的調用來完成。

    b)service開發標準流程:

         1)定義service接口:接口的定義利於寫作開發。命名:表名Service

              注意:service接口中方法的定義,取決於網站要給用戶提供什麼樣的功能,完成什麼樣的需求。

         2)接口的實現     命名:接口名Impl

2、在service中必須做手動控制事務

   a)JDBC中的事務:

        1)JDBC中的事務的管理對象時Connection

        2)JDBC中事務默認自動提交,一條sql自成一個事務。

        3)設置手動控制事務:

               conn.setAutoCommit(false);    //寫在獲取Connection之後

               手動提交事務:conn.commit();   //業務操作完成後

               手動迴歸滾事務:conn.rollback(); //出現異常的時候回滾

   b)在service中必須做手動控制事務:

       1)目的:保證Dao與service使用同一連接對象;

             注意:DAO層不關閉連接,在service中關閉;

   c)如何保證dao、service使用同一個連接

        1)在dao的方法上聲明形參,來接收service的Connection   不建議使用,這種方法存在API的入侵,不利於程序維護

        2)JDBCUtil重構

       顯然我們的程序每次都處於一個線程當中,所以我們將Connection對象存入當前線程中,未來只要當前線程中的組件需要Connection,不必創建新的,直接到當前線程中拿即可。

       實現方式:利用ThreadLocal對象:

       作用:ThreadLocal可以維護一個當前線程的局部變量,將一個對象綁定到當前線程中保存。這個對象被當前線程共享。

       使用:創建:ThreadLocal<T> tol = new ThreadLocal<T>();

                 存值:tol.set(T value);

                 取值:T t = tol.get();

                 移除:tol.remove();

        特點:一個線程,只能獲取到自己線程內部的局部變量,多個線程間不會相互影響。

    d)ThreadLocal原理:

        tol.set(value);     // 將當前對象(tol)作爲key, value作爲值,存入當前線程

        tol.get();             //  將當前對象(tol)作爲key , 到當前線程中取出對應的值

    源代碼剖析如下:



JDBCUtil.java 更改後:

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

public class JDBCUtil {
	public static Properties p = new Properties();
	static{
		InputStream ins = null;
		try {
			//借用類加載的輸入流
			ins = JDBCUtil.class.getResourceAsStream("/JDBC.properties");
			p.load(ins);//載入配置文件
			Class.forName(p.getProperty("driverClassName"));
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			try {
				ins.close();
			} catch (IOException e) {
				e.printStackTrace();
			}	
		}	
	}
	//創建一個ThreadLocal對象,用於將Connection綁定到當前線程中
	private static ThreadLocal<Connection> tol = new ThreadLocal<Connection>();
	public static Connection getConnection(){
		Connection conn = tol.get();
		if(conn==null){
			try {
				conn = DriverManager.getConnection(p.getProperty("url"),p.getProperty("username"),p.getProperty("password"));
			} catch (SQLException e) {
				e.printStackTrace();
			}
			tol.set(conn);
		}
		return conn;
	}
	public static void closeAll(PreparedStatement ps,Connection conn,ResultSet rs){
		try{
			if(rs != null){ // 避免空指針異常
				rs.close();
			}
			if(ps != null){
				ps.close();
			}
			if(conn != null){
				conn.close();
				tol.remove();  //要移除
			}
		}catch(Exception e){
			e.printStackTrace();
		}
	}
}

3、三層架構:


a)三層架構體系,是邏輯上的三層,按照完成功能不同,所做事宜不同,將項目分爲三個層次;

b)       視圖層: 涉及技術:HTML/JSP         主要職責:與用戶進行交互

      業務邏輯層:service層:使用JDBC技術   主要職責:完成業務功能

      數據訪問層:    Dao層:使用JDBC技術    主要職責:對數據庫表進行CRUD操作

 c)分層的優點:

 1)整個項目的組件之間耦合度低,某一層的改變,不會影響整個系統的運行。

 2)開發人員可以只去關注系統中的某一個層次

 3)利於協作開發

 4)後期的可維護性高

4、封裝一個日期類型轉換的工具類

java.sql.Date ----------> java.util.Date             java.util.Date ----------->java.sql.Date

DateUtil.java

public class DateUtil {
	public static java.util.Date utilDate(java.sql.Date date) throws ParseException{
		SimpleDateFormat dsf = new SimpleDateFormat("yyyy-MM-dd");
		java.util.Date utilDate = dsf.parse(date.toString());
		return utilDate;
	}
	
	public static java.sql.Date sqlDate(java.util.Date date){
		long time = date.getTime();
		java.sql.Date sqlDate = new java.sql.Date(time);
		return sqlDate;
	}
}

5、service層步驟總結:

     service層的概念: 主要封裝業務功能。 需要通過調用DAO來完成。

     service中需要做的事:

     1. 必須手動控制事務:  conn.setAutoCommit(false);

     2. 手動提交事務: conn.commit();

     3. 手動回滾事務: conn.rollback();

     4. 調用DAO

     5. 數據的處理和驗證

     注意事項: 當service和 dao 使用同一個連接對象時, 連接不在dao關閉, 在service中關閉。

6、完整的事例:(通訊錄實現)

JDBCUtil.java、Person.java、PersonDao.java在JDBC(2)中有詳細代碼:

TelBookService.java

import java.util.List;

public interface TelbookService {
	  //通過Id查找聯繫人
	  public Person getPersonById(Integer id);
	
	  //添加聯繫人需要使用的業務方法
    public void regist(String name,String mobile,String telphone,String email,String city,String birth) ;
    
    
    //獲得所有的聯繫人的業務方法
    public List<Person> getAllPerson() ;
    
    
    //根據聯繫人姓名查找聯繫人的業務方法
    public List<Person> getPersonByName(String name);
    
    
    //根據手機號碼查詢相關的聯繫人的業務方法
    public List<Person> getPersonByMobile(String mobile);
    
    //刪除聯繫人需要調用的業務方法
    public void dropPersonById(Integer id) ;
  
  	//編輯聯繫人信息需要調用的業務方法
  	public void editPersonMessage(Integer id,String name,String mobile,String telphone,String email,String city,String date );

    //獲得本月過生日的聯繫人編號
    public List<Person> happyBirthday() ;
}

TelBookServiceImpl.java

import java.sql.Connection;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class TelBookServiceImpl implements TelbookService {

	@Override
	public Person getPersonById(Integer id) {
		Connection conn = null;
		try{
			conn = JDBCUtil.getConnection();
			//手動控制事務
			conn.setAutoCommit(false);
			PersonDao personDao = new PersonDaoImpl();
			Person person = personDao.queryPersonById(id);
			conn.commit();
			return person;
		}catch(Exception e){
			try {
				conn.rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
			e.printStackTrace();
			throw new RuntimeException("獲取信息失敗,請檢查網絡!");
		}finally{
			JDBCUtil.closeAll(null, conn, null);
		}
	}

	@Override
	public void regist(String name, String mobile, String telphone,
			String email, String city, String birth) {
			Person p = new Person();
			p.setName(name);
			p.setMobile(mobile);
			p.setTelphone(telphone);
			p.setEmail(email);
			p.setCity(city);
			SimpleDateFormat date = new SimpleDateFormat("yyyy-MM-dd");
			Date d;
			try {
				d = date.parse(birth);
			} catch (ParseException e1) {
				e1.printStackTrace();
				throw new RuntimeException("日期格式錯誤!");
			}
			p.setDate(d);
			Connection conn = null;
			try{
				conn = JDBCUtil.getConnection();
				conn.setAutoCommit(false);//手動設置控制事務
				PersonDao personDao = new PersonDaoImpl();
				personDao.insertPerson(p);
				conn.commit();//手動提交
				return ;
			}catch(Exception e){
				try {
					conn.rollback();
				} catch (SQLException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				e.printStackTrace();
				throw new RuntimeException("提交失敗!");
			}finally{
				JDBCUtil.closeAll(null, conn, null);
			}
	}

	@Override
	public List<Person> getAllPerson() {
		List<Person> list = new ArrayList<Person>();
		Connection conn = null;
		try{
			PersonDao personDao = new PersonDaoImpl();
			conn = JDBCUtil.getConnection();
			conn.setAutoCommit(false);
			list = personDao.queryAllPersons();
			System.out.println(conn);
			conn.commit();
			return list;
		}catch(Exception e){
			try {
				conn.rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
			throw new RuntimeException("網絡出故障!");
		}finally{
			JDBCUtil.closeAll(null, conn, null);
		}
	}

	@Override
	public List<Person> getPersonByName(String name) {
		Connection conn = null;
		List<Person>  list = new ArrayList<Person>();
		try{
			conn = JDBCUtil.getConnection();
			conn.setAutoCommit(false);
			PersonDao personDao = new PersonDaoImpl();
			list = personDao.queryPersonsByName(name);
			conn.commit();
			return list;
		}catch(Exception e){
			try {
				conn.rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
			throw new RuntimeException("網絡出故障!");
		}finally{
			JDBCUtil.closeAll(null, conn, null);
		}
		
	}

	@Override
	public List<Person> getPersonByMobile(String mobile) {
		List<Person> list = new ArrayList<Person>();
		Connection conn = null;
		try{
			conn = JDBCUtil.getConnection();
			conn.setAutoCommit(false);
			PersonDao personDao = new PersonDaoImpl();
			list = personDao.queryPersonsByMobile(mobile);
			conn.commit();
			return list;
		}catch(Exception e){
			try {
				conn.rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
			throw new RuntimeException("網絡出現問題!");
		}finally{
			JDBCUtil.closeAll(null, conn, null);
		}
	} 

	@Override
	public void dropPersonById(Integer id) {
		Connection conn = null;
		try{
			conn = JDBCUtil.getConnection();
			conn.setAutoCommit(false);
			PersonDao personDao = new PersonDaoImpl();
			personDao.deletePerson(id);
			conn.commit();
		}catch(Exception e){
			e.printStackTrace();
			try {
				conn.rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
		}finally{
			JDBCUtil.closeAll(null, conn, null);
		}
	}

	@Override
	public void editPersonMessage(Integer id, String name, String mobile,
			String telphone, String email, String city, String date) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		Date d = null;
		try {
			d = sdf.parse(date);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		Person person = new Person(id,name,mobile,telphone,email,city,d);
		Connection conn = null;
		try{
			conn = JDBCUtil.getConnection();
			conn.setAutoCommit(false);
			PersonDao personDao = new PersonDaoImpl();
			personDao.updatePerson(person);
			conn.commit();
		}catch(Exception e){
			try {
				conn.rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
		}finally{
			JDBCUtil.closeAll(null, conn, null);
		}
		
	}

	@Override
	public List<Person> happyBirthday() {
		Connection conn = null;
		List<Person> list = new ArrayList<Person>();
		try{
			conn = JDBCUtil.getConnection();
			conn.setAutoCommit(false);
			PersonDao personDao = new PersonDaoImpl();
			list = personDao.queryPersonsByMonth();
			conn.commit();
			return list;
		}catch(Exception e){
			try {
				conn.rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
			throw new RuntimeException("網絡故障!");
		}finally{
			JDBCUtil.closeAll(null, conn, null);
		}
	}

}

TelBookView.java

import java.util.List;
import java.util.Scanner;

import org.junit.Test;

public class TelBookView {
	private Scanner sc=new Scanner(System.in);
	private TelbookService  service=null;
	public TelBookView() {
		try{
			service = new TelBookServiceImpl();
		}catch(Exception e){}
	}
	@Test
	public void showMainView(){
		while(true){
			System.out.println("***************歡迎訪問通訊錄***************");
			System.out.println("1.顯示所有聯繫人     2.按姓名查找聯繫人     3.按號碼查找聯繫人");
			System.out.println("4.添加聯繫人            5.刪除聯繫人                6.修改聯繫人信息");
			System.out.println("7.生日快樂     8.退出");
			System.out.println("請選擇操作:");
			int selected=sc.nextInt();
			requestDispatcher(selected);
		}
	}
	public void  requestDispatcher(int selected) {
		try {
			switch(selected){
			case 1:{ showAllPerson(); break;}
			case 2:{ showPersonsByName(); break;}
			case 3:{ showPersonsByMobil();break;}
			case 4:{ addPerson(); break;}
			case 5:{ dropPersonById(); break;}
			case 6:{changePersonMessageById(); break;}
			case 7:{ sayHappy(); break;}
			case 8:{ 
				System.out.println("--------------------謝謝使用,再見------------------");
				System.exit(0); 
				break;
			}
			default:{
				throw new Exception("輸入錯誤,請考慮重新選擇!");
			}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	//用戶選擇功能1,顯示所有聯繫人
	public void  showAllPerson() throws Exception{
		//調用service的查詢方法,查詢所有的聯繫人
      List<Person>  list=service.getAllPerson();
      //調用本類的方法顯示聯繫人信息
      showPersons(list);
	}
	//只供本類其他方法是用,用表格形式顯示list集合裏的聯繫人信息
	private void showPersons(List<Person> list) throws Exception{
		System.out.println("Id\tName\t  Mobile  \t  Telphone  \t    Email    \t  City  \t  Birthday  ");
		for(Person p:list){
	    	   System.out.println(p.getId()+"\t"+p.getName()+"\t"+p.getMobile()+"\t"+p.getTelphone()+"\t"+p.getEmail()+"\t"+p.getCity()+"\t"+p.getDate());
	    }
	}
	//用戶選擇功能2,按姓名查詢聯繫人,允許模糊查詢
   public void showPersonsByName() throws Exception{
	   System.out.println("請輸入需要查詢的聯繫人姓名(可以模糊查詢):");
	   String name=sc.next();
	   //調用service方法查詢相關數據
	   List<Person>  list=service.getPersonByName(name);
	    //調用本類的方法顯示聯繫人信息
      showPersons(list);
   }
   //用戶選擇功能3,按手機查詢聯繫人,允許模糊查詢
	public void showPersonsByMobil() throws Exception{
		 System.out.println("請輸入需要查詢的聯繫人手機號碼(可以模糊查詢):");
		 String mobile=sc.next();
		 //調用service方法查詢相關數據
	   List<Person>  list=service.getPersonByMobile(mobile);
	    //調用本類的方法顯示聯繫人信息
      showPersons(list);
	}
	//用戶選擇功能4,添加聯繫人,允許用戶名重複
    public void addPerson() throws Exception{
    	System.out.println("請輸入聯繫人姓名:");
    	String name=sc.next();
    	System.out.println("請輸入聯繫人手機號碼:");
    	String mobile=sc.next();
    	System.out.println("請輸入聯繫人座機號碼:");
    	String telphone=sc.next();
    	System.out.println("請輸入聯繫人email:");
    	String email=sc.next();
    	System.out.println("請輸入聯繫人地址:");
    	String city=sc.next();
    	System.out.println("請輸入生日(1980-6-23):");
    	String date=sc.next();
    	
    	//調用service的regist()
    	service.regist(name, mobile, telphone, email, city, date);
    	
    	System.out.println("添加聯繫人成功!!!!");
    }
    //用戶選擇功能5,刪除聯繫人,需要輸入聯繫人的id
    public void dropPersonById() throws Exception{
       System.out.println("請輸入需要刪除的聯繫人的id:");
		   int id=sc.nextInt();	
		   //調用service的方法刪除聯繫人
		   service.dropPersonById(id);
		   System.out.println("-----------刪除成功----------");
    }
    //首先需要用戶輸入被修改用戶的id,將該用戶信息顯示在屏幕上.
    //目前修改聯繫人只能全表修改,必須給定除id以外的所有值
    public void changePersonMessageById() throws Exception{
    	System.out.println("請輸入需要修改的聯繫人的編號(id):	");
		  int id=sc.nextInt();	
		  //調用service的根據id查詢聯繫人方法,獲得聯繫人具體信息並且顯示
		  Person  p=service.getPersonById(id);
		  System.out.println("您要修改的聯繫人具體信息如下:");
		  System.out.println("Id\tName\t  Mobile  \t  Telphone  \t    Email    \t  City  \t  Birthday  ");
      System.out.println(p.getId()+"\t"+p.getName()+"\t"+p.getMobile()+"\t"+p.getTelphone()+"\t"+p.getEmail()+"\t"+p.getCity()+"\t"+p.getDate());
      //用戶輸入修改信息
      System.out.println("請輸入聯繫人姓名:");
    	String name=sc.next();
    	System.out.println("請輸入聯繫人手機號碼:");
    	String mobile=sc.next();
    	System.out.println("請輸入聯繫人座機號碼:");
    	String telphone=sc.next();
    	System.out.println("請輸入聯繫人email:");
    	String email=sc.next();
    	System.out.println("請輸入聯繫人地址:");
    	String city=sc.next();
    	System.out.println("請輸入生日(1980-6-23):");
    	String date=sc.next();
    	//調用service裏的修改聯繫人的方法
    	service.editPersonMessage(id,name,mobile,telphone,email,city,date);
      System.out.println("-----------修改成功----------");
    }
    //向本月過生日的聯繫人發送happybirthday短信
 
    public void sayHappy(){
    	//調用service的查詢方法,查詢所有過生日的聯繫人
      List<Person>  list=service.happyBirthday();
      //調用本類的方法顯示聯繫人信息
      try {
		showPersons(list);
	} catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
      System.out.println("哈哈,祝你年年有今日,歲歲有今朝");
    }
}

以上均是java project工程;

    

發佈了49 篇原創文章 · 獲贊 14 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章