JDBC核心基础——考虑事务后的代码实现和优化DAO类

〇:考虑了数据库事务后的代码实现步骤

  1. 获取数据库的连接
    1. 可以选择手动获取连接
    2. 可以选择数据库连接池
  2. 事务的体现:conn.setAutoCommit(false);
  3. 诸多的 DML 操作,作为一个事务出现
    1. 可以选择手动使用 PreparedStatement 实现
    2. 可以选择使用 Apache 提供的 dbutils.jar 中的 QueryRunner 类
  4. 如果出现了异常就:conn.rollback();
  5. 关闭资源
    1. 可以选择手动关闭资源
    2. 可以选择使用 Apache 提供的 Dbutils 类的关闭方法

I:提供一个操作数据表的基本的DAO类(Version 2.0)

  1. 在 BaseDAO 抽象类中声明一个 T 类型的泛型参数
  2. 在 BaseDAO 类中声明一个 Class<T> 类型的属性 clazz,提供给内部的方法使用
  3. 获取对象前对 clazz 属性进行赋值,可以使用显式,构造器,代码块赋值,此处使用代码块赋值
  4. 获取当前对象的类,再获取此类的带泛型的父类 gsc
  5. 将带泛型的父类 gsc 强转成 pt
  6. 通过 pt 调用方法获取父类泛型的参数数组 aty
  7. 获取泛型的第一个参数进行强转并给 clazz 赋值
@SuppressWarnings("unchecked")
public abstract class BaseDAO<T> {
	private Class<T> clazz = null;

	{
		Type gsc = this.getClass().getGenericSuperclass();
		ParameterizedType pt = (ParameterizedType) gsc;
		Type[] aty = pt.getActualTypeArguments();
		clazz = (Class<T>) aty[0];
	}

	public int Update(Connection conn, String sql, Object... args) {
		PreparedStatement ps = null;
		try {
			ps = conn.prepareStatement(sql);
			for (int i = 0; i < args.length; i++) {
				ps.setObject(i + 1, args[i]);
			}
			int i = ps.executeUpdate();
			return i;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JDBCUtils.closeResource(null, ps);
		}
		return 0;
	}

	public T Query(Connection conn, String sql, Object... args) {
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			ps = conn.prepareStatement(sql);
			for (int i = 0; i < args.length; i++) {
				ps.setObject(i + 1, args[i]);
			}
			rs = ps.executeQuery();
			ResultSetMetaData rsmd = rs.getMetaData();
			int columnCount = rsmd.getColumnCount();
			if (rs.next()) {
				T t = clazz.newInstance();
				for (int i = 0; i < columnCount; i++) {
					Object columnValue = rs.getObject(i + 1);
					String ColumnLabel = rsmd.getColumnLabel(i + 1);
					Field field = clazz.getDeclaredField(ColumnLabel);
					field.setAccessible(true);
					field.set(t, columnValue);
				}
				return t;
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JDBCUtils.closeResource(null, ps, rs);
		}
		return null;
	}

	public List<T> QueryAll(Connection conn, String sql, Object... args) {
		PreparedStatement ps = null;
		ResultSet rs = null;
		List<T> list;
		try {
			ps = conn.prepareStatement(sql);
			for (int i = 0; i < args.length; i++) {
				ps.setObject(i + 1, args[i]);
			}
			rs = ps.executeQuery();
			ResultSetMetaData rsmd = rs.getMetaData();
			int columnCount = rsmd.getColumnCount();
			list = new ArrayList<T>();
			while (rs.next()) {
				T t = clazz.newInstance();
				for (int i = 0; i < columnCount; i++) {
					Object columnValue = rs.getObject(i + 1);
					String ColumnLabel = rsmd.getColumnLabel(i + 1);
					Field field = clazz.getDeclaredField(ColumnLabel);
					field.setAccessible(true);
					field.set(t, columnValue);
				}
				list.add(t);
			}
			return list;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JDBCUtils.closeResource(null, ps, rs);
		}
		return null;
	}

	public <E> E getValue(Connection conn, String sql, Object... args) {
		PreparedStatement ps = null;
		try {
			ps = conn.prepareStatement(sql);
			for (int i = 0; i < args.length; i++) {
				ps.setObject(i + 1, args[i]);
			}
			ResultSet rs = ps.executeQuery();
			if (rs.next()) {
				Object object = rs.getObject(1);
				return (E) object;
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JDBCUtils.closeResource(null, ps);
		}
		return null;
	}
}

II:操作指定数据表的接口

public interface CustomerDAO {
	void insert(Connection conn, Customer cust);

	void deleteById(Connection conn, int id);

	void update(Connection conn, Customer cust);

	Customer getCustomerById(Connection conn, int id);

	List<Customer> getAll(Connection conn);

	Long getCount(Connection conn);
	
	Date getMaxBirth(Connection conn);
}

III:升级操作指定数据表的类(Version 2.0)

  1. 在继承父类 BaseDAO 的泛型参数中指明要操作的具体的类,此处为 Customer 类
  2. 设法获取父类的泛型参数,才可以使用反射机制,为 BaseDAO 中的方法获取运行时类的对象
public class CustomerDAOImpl extends BaseDAO<Customer> implements CustomerDAO {

	@Override
	public void insert(Connection conn, Customer cust) {
		String sql = "insert into customers(name,email,birth) values(?,?,?)";
		Update(conn, sql, cust.getName(), cust.getEmail(), cust.getBirth());
	}

	@Override
	public void deleteById(Connection conn, int id) {
		String sql = "delete from customers where id = ?";
		Update(conn, sql, id);
	}

	@Override
	public void update(Connection conn, Customer cust) {
		String sql = "update customers set name = ?,email = ?,birth = ? where id = ?";
		Update(conn, sql, cust.getName(), cust.getEmail(), cust.getBirth(), cust.getId());
	}

	@Override
	public Customer getCustomerById(Connection conn, int id) {
		String sql = "select id,name,email,birth from customers where id = ?";
		Customer customer = Query(conn, sql, id);
		return customer;
	}

	@Override
	public List<Customer> getAll(Connection conn) {
		String sql = "select id,name,email,birth from customers";
		List<Customer> list = QueryAll(conn, sql);
		return list;
	}

	@Override
	public Long getCount(Connection conn) {
		String sql = "select count(*) from customers";
		return getValue(conn, sql);
	}

	@Override
	public Date getMaxBirth(Connection conn) {
		String sql = "select max(birth) from customers";
		return getValue(conn, sql);
	}
}

IV:对实现类中所实现的方法进行单元测试(Version 2.0)

public class CustomerDAOImplTest {
	private CustomerDAOImpl dao = new CustomerDAOImpl();

	@Test
	public void testInsert() {
		Connection conn = null;
		try {
			conn = JDBCUtils.getConnection();
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
			java.util.Date date = sdf.parse("2020-3-8");
			Customer cust = new Customer("尚硅谷", "atguigu@gmail.com", new java.sql.Date(date.getTime()));
			dao.insert(conn, cust);
			System.out.println("添加成功");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JDBCUtils.closeResource(conn, null);
		}
	}

	@Test
	public void testDeleteById() {
		Connection conn = null;
		try {
			conn = JDBCUtils.getConnection();
			dao.deleteById(conn, 25);
			System.out.println("删除成功");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JDBCUtils.closeResource(conn, null);
		}
	}

	@Test
	public void testUpdate() {
		Connection conn = null;
		try {
			conn = JDBCUtils.getConnection();
			Customer cust = new Customer(21, "康师傅", "shkstart@gmail.com", new java.sql.Date(3235879865235L));
			dao.update(conn, cust);
			System.out.println("更新成功");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JDBCUtils.closeResource(conn, null);
		}
	}

	@Test
	public void testGetCustomerById() {
		Connection conn = null;
		try {
			conn = JDBCUtils.getConnection();
			Customer cust = dao.getCustomerById(conn, 21);
			System.out.println(cust);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JDBCUtils.closeResource(conn, null);
		}
	}

	@Test
	public void testGetAll() {
		Connection conn = null;
		try {
			conn = JDBCUtils.getConnection();
			List<Customer> list = dao.getAll(conn);
			Iterator<Customer> iterator = list.iterator();
			while (iterator.hasNext()) {
				Customer customer = iterator.next();
				System.out.println(customer);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JDBCUtils.closeResource(conn, null);
		}
	}

	@Test
	public void testGetCount() {
		Connection conn = null;
		try {
			conn = JDBCUtils.getConnection();
			Long count = dao.getCount(conn);
			System.out.println(count);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JDBCUtils.closeResource(conn, null);
		}
	}

	@Test
	public void testGetMaxBirth() {
		Connection conn = null;
		try {
			conn = JDBCUtils.getConnection();
			Date maxBirth = dao.getMaxBirth(conn);
			System.out.println(maxBirth);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JDBCUtils.closeResource(conn, null);
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值