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 tol = new ThreadLocal();

                 存值:tol.set(T value);

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

                 移除:tol.remove();

        特点:一个线程,只能获取到自己线程内部的局部变量,多个线程间不会相互影响。

    d)ThreadLocal原理:

        tol.set(value);     // 将当前对象(tol)作为key, value作为值,存入当前线程

        tol.get();             //  将当前对象(tol)作为key , 到当前线程中取出对应的值

    源代码剖析如下:

JDBC(3)----------service层以及三层架构的完整的JDBC实例_第1张图片


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 tol = new ThreadLocal();
	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、三层架构:

JDBC(3)----------service层以及三层架构的完整的JDBC实例_第2张图片

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 getAllPerson() ;
    
    
    //根据联系人姓名查找联系人的业务方法
    public List getPersonByName(String name);
    
    
    //根据手机号码查询相关的联系人的业务方法
    public List 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 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 getAllPerson() {
		List list = new ArrayList();
		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 getPersonByName(String name) {
		Connection conn = null;
		List  list = new ArrayList();
		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 getPersonByMobile(String mobile) {
		List list = new ArrayList();
		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 happyBirthday() {
		Connection conn = null;
		List list = new ArrayList();
		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  list=service.getAllPerson();
      //调用本类的方法显示联系人信息
      showPersons(list);
	}
	//只供本类其他方法是用,用表格形式显示list集合里的联系人信息
	private void showPersons(List 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  list=service.getPersonByName(name);
	    //调用本类的方法显示联系人信息
      showPersons(list);
   }
   //用户选择功能3,按手机查询联系人,允许模糊查询
	public void showPersonsByMobil() throws Exception{
		 System.out.println("请输入需要查询的联系人手机号码(可以模糊查询):");
		 String mobile=sc.next();
		 //调用service方法查询相关数据
	   List  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  list=service.happyBirthday();
      //调用本类的方法显示联系人信息
      try {
		showPersons(list);
	} catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
      System.out.println("哈哈,祝你年年有今日,岁岁有今朝");
    }
}

以上均是java project工程;

    

你可能感兴趣的:(JAVA编程)