Basedao

Basedao

 

为什么要建立basedao:

若有新的功能需要添加,但是该功能与现有的dao层的接口的功能无关,

就需要新建一个dao层,实现要添加的方法,如果有和userdao或者recorddao相类似,但是参数类型不同的方法,也得再写一遍方法,这样大大提高了代码的工作量。所以建立basedao,把通用的方法放到里面,让其他的dao层接口继承该接口,其他的dao层实现类也继承该实现类,提高了代码的复用。

建立basedao好处:

为了贯彻单一职责原则,收集共性(所有dao层的通用方法),让其他dao负责他们相关的职责

单一职责原则

  不要存在多于一个导致类改变的原因

  简单的说,一个类就负责一项职责

  * 没有说一个类只能有一个方法

  优点:

1) 降低类的复杂度,一个类只负责一项职责,其逻辑肯定比负责多项职责简单的多

2) 提高类的可读性,提高系统的可维护性

3) 变更引起的风险降低,这个原则遵循的好,可以显著降低对其他功能的影响

4) 需要说明的是,单一职责原则不是OOP程序所独有的,只要是模块化的程序设计,都必须遵守这个原则

 

basedao的逻辑方法

 

在dao层新建basedao,其他dao层接口继承basedao

Basedao里写泛用性较强的抽象方法

Basedao实现类里实现basedao接口的方法,其他dao层实现类继承该方法

若子接口有自有的方法,则额外扩展即可.

因为Dao层的实现子类(UserDaoImpl,RecordDaoImpl)继承了basedao实现类(BaseDaoImpl)的方法,所以不需要额外写和basedao功能相同的方法,所以子类直接调用方法即可

#2. 案例中的baseDao必须满足以下条件才能使用

 * 1. javaBean类名必须和表名一致

 * 2. javaBean属性名必须和列名一致

 * 3. 主键必须叫id

 * 4. 必须用包装类型 int -> Integer

 * 5. 必须有公开的无参构造

 * 6. get set方法必须规范

具体实现

 

Basedao是泛型接口:

//泛型接口,通配符T,可以存放任意类型,传入的是什么类型,方法里面接收到的就是该类型

public interface BaseDao<T> {

//传入的对象可以是任何类型,抛出sql异常交给view层打印,让用户知道sql语句的问题

public interface BaseDao<T> {

	void insert(T t,Connection conn) throws SQLException;
	
	void delete(int id,Connection conn) throws SQLException;
	
	void update(T t,Connection conn) throws SQLException;
	
	T querybyid(int id,Connection conn) throws SQLException;
	
	List<T> queryAll(Connection conn) throws SQLException;
	
	int queryCount(Connection conn)throws SQLException;
	
	
}

 

BaseDaoImpl实现类

构造方法:获取当前对象的泛型(用于组装返回对象)

public class BaseDaoImpl<T> implements BaseDao<T> {
	private Class<?> gclass;

//构造方法:

public BaseDaoImpl() {

// 获取泛型类型 - T

//Basedaoimpl被userdaoimpl继承

//This.getclass调用构造器的对象class com.bwf.dao.impl.UserDaoImpl

//getGenericSuperclass()获得带有泛型的父类com.bwf.dao.impl.BaseDaoImpl<com.bwf.bean.User>

//ParameterizedType参数化类型,即泛型

//Type是 Java 编程语言中所有类型的公共高级接口。它们包括原始类型、参数化类型、数组类型、类型变量和基本类型。

ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();

//getActualTypeArguments获取参数化类型的数组,泛型可能有多个class com.bwf.bean.User

gClass = (Class<?>) pt.getActualTypeArguments()[0];

}

  

查询方法:返回的对象T是通过构造方法获得的

@Override
	public T querybyid(Connection conn, int id) throws SQLException {

		String sql = "select *from " + gclass.getSimpleName() + " where id=?";
		PreparedStatement ps = conn.prepareStatement(sql);
		ps.setObject(1, id);
		ResultSet rs = ps.executeQuery();
		// 实例化对象
		T t;
		try {
			t = (T) gclass.newInstance();
			if (rs.next()) {
				Field[] df = gclass.getDeclaredFields();
				for (int i = 0; i < df.length; i++) {
					Field f = df[i];
					// 拿到属性的值
					Object value = rs.getObject(f.getName());
					// 拿到setter方法
					String setter = "set" + f.getName().substring(0, 1).toUpperCase() + f.getName().substring(1);
					// 获得对象的属性
					Method method = gclass.getMethod(setter, value.getClass());
					method.invoke(t, value);
				}
			}
			return t;
		} 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();
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;

	}

更新方法:(用到了反射)

	@Override
	public void update(Connection conn, T t) throws SQLException {
		// 获得类对象
		Class<?> class1 = t.getClass();
		String tableName = class1.getSimpleName();
		String getName = null;
		// 获得成员属性
		Field[] df = class1.getDeclaredFields();
		// 拼接sql语句
		// update User set id=?,uname=?,upwd=?,money=? where id=?
		String sql = "update " + tableName + " set ";
		for (int i = 0; i < df.length; i++) {
			Field field = df[i];
			getName = "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);

			sql += field.getName() + "=?";
			if (i < df.length - 1) {
				sql += ",";
			} else {
				sql += " where id=?";
			}
		}
		// update User set id=?,uname=?,upwd=?,money=? where id=?
		// 填充占位符
		PreparedStatement ps = conn.prepareStatement(sql);
		// 存放条件表达式 即id,数组下标第一
		String where;
		for (int i = 0; i < df.length; i++) {
			Field field = df[i];
			getName = "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
			// 存放条件表达式 即id,数组下标第0位,填充第length+1位占位符
			try {
			if (i == 0) {
				where = getName;
				// 反射调用getId方法并把值拼接到最后一位
				
					ps.setObject(df.length + 1, class1.getDeclaredMethod(where).invoke(t));
				
			}
			Method method = class1.getDeclaredMethod(getName);

			ps.setObject(i + 1, method.invoke(t));
			} 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();
			} catch (NoSuchMethodException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (SecurityException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}
		int executeUpdate = ps.executeUpdate();
		System.out.println(sql);
	}

basedao类实现basedao接口

因为basedaoimpl需要通用,所以basedaoimpl的泛型类型也是T

public class BaseDaoImpl<T> implements BaseDao<T> 

其他dao层实现类如何继承basedao实现类

子类/接口继承泛型类的写法

在子类/接口不设置泛型,而在父类明确的定义一个泛型类型

public interface RecordDao extends BaseDao<Record>

public class RecordDaoImpl extends BaseDaoImpl<Record>implements RecordDao {