JDBC简单操作(三层架构以及简单工厂的实现)

写一个初始实现类

package niit.jdbc.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class JdbcUtil {
	static String URL = "jdbc:mysql://localhost:3306/niit?characterEncoding=utf8";
	static String USER = "root";
	static String PASSWORD = "root";
	
	static ThreadLocal<Connection> threadLocal = new ThreadLocal<>();
	public static Connection getConnection(){
		Connection con = threadLocal.get();
		try {
			Class.forName("com.mysql.jdbc.Driver");
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			if(threadLocal.get()==null){
				con = DriverManager.getConnection(URL,USER,PASSWORD);
				threadLocal.set(con);
			}
			
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return con;
		
	}
	public static TransactionManager getTransactionManager(){
		return new TransactionManager(getConnection());
	}
	
	
	public static void free(Connection con){
		try {
			con.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			threadLocal.remove();
		}
	}
}
里面有一个getTransactionManager的方法,是用于事务的操作。主要用于回滚。这个我后面解释一下


写一个工具类,用于数据库的增删改查功能

package niit.jdbc.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import niit.jdbc.util.JdbcUtil;

public  class BaseDao <T>{
	
	
	public void upDate(String sql,List<Object> list){
		Connection con = null;
		PreparedStatement pre = null;
		con = JdbcUtil.getConnection();
		try {
			pre = con.prepareStatement(sql);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		int temp = 1;
		
		for (Object object : list) {
			try {
				pre.setObject(temp, object);
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	
			temp++;
		}
		try {
			pre.executeUpdate();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			try {
				if(con.getAutoCommit()){
					JdbcUtil.free(con);
				}
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	}
	public List<T> select(String sql,List<Object> selectList,MapRower<T>mr){
		Connection con = null;
		PreparedStatement pre = null;
		ResultSet rs = null;
		
		
		List<T> list = new ArrayList<>();
		con = JdbcUtil.getConnection();
		try {
			pre = con.prepareStatement(sql);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		int temp = 1;
		
		for (Object object : selectList) {
			try {
				pre.setObject(temp, object);
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	
			temp++;
		}
		
		try {
			rs = pre.executeQuery();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			if(rs != null){
				list =  mr.maprower(rs);
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			JdbcUtil.free(con);
		}
		return list;
	}
	
}

我们用一个创建一个Student表,分别包含属性,学号,姓名,年龄以及地址。并创建Student的类用于Beans,我就不写了


还有就是在Update方法中关闭连接的时候我做了一下判断,主要是用于事务的实现。因为假如有两个表,两个表有外键连接,我们去删除一个表中的外键字段,就要先去另外一个表中删掉使用这个字段的所有字段。如果发生了断电或者异常只是执行了一半,我们必须实现回滚的操作。所以要用到事务。先看一下表

import java.sql.Connection;
import java.sql.SQLException;

public class TransactionManager {
	private Connection con;

	public TransactionManager(Connection con) {
		super();
		this.con = con;
	}
	//关闭自动提交
	public void statrOfCommit(){
		try {
			con.setAutoCommit(false);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	//提交
	public void CommintAndFree(){
		try {
			con.commit();
			JdbcUtil.free(con);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	//回流
	public void RollbackAndFree(){
		try {
			con.rollback();
			JdbcUtil.free(con);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
因为我们要进行回滚就要先关闭系统的自动提交,所以用这个方法去判断我们执行的操作是否有可能需要回滚,如果不需要,就可以关闭方法

还有一个就是因为我想保证在一个线程中只用一个连接,这样的话,可以加大问的便捷性

在上上段代码中,用了MapRower<T>mr   这是一个接口,用这个接口的主要目的就是因为得到ResultSet后不能直接使用Student类别转换,所以在MapRower中的maprower传入ResultSet并得到List   这样可以更加灵活是用数据库的查询语句。

我使用maprower是使用匿名内部类实现,如下:

package niit.jdbc.dao.impl;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import niit.jdbc.dao.BaseDao;
import niit.jdbc.po.StudentPO;
import niit.jdbc.vo.Student;
import niit.jdbc.dao.MapRower;
import niit.jdbc.dao.StudentDao;

public class StudentDaoImpl extends BaseDao<Student> implements StudentDao{
	
	public void getInsert(Student stu){
		String sql = "insert into student values (?,?,?,?)";
		List<Object> list = new ArrayList<>();
		list.add(stu.getSno());
		list.add(stu.getSname());
		list.add(stu.getAddress());
		list.add(stu.getAge());
		this.upDate(sql, list);
	}
	public void getSelect(int sno){
		String sql = "delete from student where sno = ?";
		List<Object> list = new ArrayList<>();
		list.add(sno);
		this.upDate(sql, list);
	}
	/*
	 * 没改呢
	 */
	public void getUpdate(Student stu){
		String sql = "insert into student values (?,?,?,?)";
		List<Object> list = new ArrayList<>();
		list.add(stu.getSno());
		list.add(stu.getSname());
		list.add(stu.getAddress());
		list.add(stu.getAge());
		this.upDate(sql, list);
	}
	
	
	public List<Student> getSelect(StudentPO stupo){
		
		String sql = "select * from student where 1=1";
		List<Object> getStu = new ArrayList<>();
		if(stupo.getName()!=null){
			sql = sql +  " and sname = ?";
			getStu.add(stupo.getName());
		}
		if(stupo.getAgeFrom()!= null){
			sql = sql + " and age > ?";
			getStu.add(stupo.getAgeFrom());
		}
		if(stupo.getAgeTo()!= null){
			sql = sql + " and age < ?";
			getStu.add(stupo.getAgeTo());
		}
		return  this.select(sql, getStu,new MapRower<Student>(){

			@Override
			public List<Student> maprower(ResultSet rs) {
				List<Student> list = new ArrayList<>();
				Student stu = null;
				try {
					while(rs.next()){
						stu = new Student();
						stu.setSno(rs.getInt("sno"));
						stu.setSname(rs.getString("sname"));
						stu.setAddress(rs.getString("address"));
						stu.setAge(rs.getInt("age"));
						list.add(stu);
					}
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				return list;
			}
			
		});
		
	}
其中Update因为没有想好查询语句和修改值就没有写,其实比较懒而已。上面就是Student在Dao层的实现,因为避免耦合,都是使用接口实现,这里没有就不上传接口代码,接口的名字就是实现类的名字去掉impl。

可能观察到了,我在Select方法中传入的是StudentPO,StudentPO的属性包扣,姓名和年龄的区间(两个Integer,使用Integer的原因是int的NULL值的默认值是0,不方便判断),所在在查询语句可以根据姓名、年龄区间查询。

下面是Serivce层。代码如下:

package niit.jdbc.service.impl;

import java.util.List;

import niit.jdbc.dao.StudentDao;
import niit.jdbc.po.StudentPO;
import niit.jdbc.production.impl.GetStudentDaoProduction;
import niit.jdbc.service.StudentService;
import niit.jdbc.vo.Student;

public class StudentServiceImpl implements StudentService{
	private StudentDao studentdao= GetStudentDaoProduction.getS();
	@Override
	public void serviceInsert(Student stu) {
		// TODO Auto-generated method stub
		studentdao.getInsert(stu);
	}

	@Override
	public void serviceSelect(int sno) {
		// TODO Auto-generated method stub
		studentdao.getSelect(sno);
	}

	@Override
	public void serviceUpdate(Student stu) {
		// TODO Auto-generated method stub
		studentdao.getUpdate(stu);
	}

	@Override
	public List<Student> serviceSelect(StudentPO stupo) {
		// TODO Auto-generated method stub
		return studentdao.getSelect(stupo);
	}

}
其中我获取StudentDao的时候是使用简单工厂模式,这里的主要作用是用于解耦

下面是工厂接口的实现类

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

import niit.jdbc.dao.StudentDao;
import niit.jdbc.production.StudentDaoproduction;

public class StudentDaoproductionImpl implements StudentDaoproduction {

	@Override
	public StudentDao getStudenDao() {
		// TODO Auto-generated method stub
		Class clazz = null;
		try {
			clazz = Class.forName("niit.jdbc.dao.impl.StudentDaoImpl");
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		Constructor  ctor = null;
		try {
			ctor = clazz.getConstructor();
		} catch (NoSuchMethodException | SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		Object obj = null;
		try {
			obj = ctor.newInstance();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return (StudentDao) obj;
	}

}
下面是工厂的实现:
import niit.jdbc.dao.StudentDao;
import niit.jdbc.production.StudentDaoproduction;

public class GetStudentDaoProduction {
	public static StudentDao getS() {
		StudentDaoproduction sd = null;
		try {
			sd = (StudentDaoproduction) Class.forName("niit.jdbc.production.impl.StudentDaoproductionImpl")
					.newInstance();

		} catch (InstantiationException | IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		// Class.forname("niit.jdbc.production.impl.StudentDaoproductionImpl")
		// StudentDaoproductionImpl.class
		return sd.getStudenDao();
	}
}
下面就是测试类。(没有写UI,很尴尬)

package niit.jdbc.test;

import niit.jdbc.service.StudentService;
import niit.jdbc.service.impl.StudentServiceImpl;
import niit.jdbc.vo.Student;

public class Test01 {
	public static void main(String[] args) {
		StudentService ss = new StudentServiceImpl();
		Student stu = new Student();
		stu.setSno(1004);
		stu.setSname("张四");
		stu.setAddress("中关村");
		stu.setAge(50);
		ss.serviceInsert(stu);
	}
}
这个测试类就是添加语句,没有什么可说的。很简单

import niit.jdbc.service.StudentService;
import niit.jdbc.service.impl.StudentServiceImpl;
import niit.jdbc.util.JdbcUtil;
import niit.jdbc.util.TransactionManager;
import niit.jdbc.vo.Student;

public class Test02 {
	public static void main(String[] args) {
		StudentService studentSetivce = new StudentServiceImpl();
		Student stu = new Student();
		stu.setSno(1005);
		stu.setSname("张四");
		stu.setAddress("中关村");
		stu.setAge(50);
		Student stu1 = new Student();
		stu1.setSno(1006);
		stu1.setSname("张四");
		stu1.setAddress("中关村");
		stu1.setAge(50);
		TransactionManager tm = JdbcUtil.getTransactionManager();
		tm.statrOfCommit();
		try{
		studentSetivce.serviceInsert(stu);
		int i =5/0;
		System.out.println(i);
		studentSetivce.serviceInsert(stu1);
		tm.CommintAndFree();
		}catch(Exception e){
			e.printStackTrace();
			tm.RollbackAndFree();
		}
	}
}
这个测试类就是利用了一下事务的回滚操纵,在两个添加语句中故意写了一个异常。当catch到异常的时候进行回滚操作并关闭连接。如果没有catch到异常,就执行操作并关闭连接


OK,就是这样。









  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值