在DAO层中将方法转换为通用方法

时间:2018-07-28 07:35:34

标签: java generic-programming

目前,我在DAO层中有一些方法可以处理多个选择查询。我当时想的是对这三种方法都具有通用方法,以便可以将其进一步使用。这是我的方法。

public List<Customer> findAll(){

    String sql = "SELECT * FROM CUSTOMER";

    List<Customer> customers  = getJdbcTemplate().query(sql,
        new BeanPropertyRowMapper(Customer.class));

    return customers;
} 

用于查找客户的电话号码。

public List<Phone> findPhoneNumbers(int custId){

    String sql = "SELECT * FROM PHONE WHERE CUST_ID="+custId;

    List<Phone> phoneNumbers  = getJdbcTemplate().query(sql,
        new BeanPropertyRowMapper(Phone.class));

    return phoneNumbers;
} 

以此类推。

可以将这些方法转换为单个通用方法,以便可以从我的服务层调用它。任何建议或想法将不胜感激。

3 个答案:

答案 0 :(得分:2)

您可以使用通用方法,并让调用者指定类。

findAll

很容易
public <T> List<T> findAll(Class<T> entityClass, String tableName){

    String sql = "SELECT * FROM " + tableName;

    return getJdbcTemplate().query(sql,
        new BeanPropertyRowMapper(entityClass));

    return phoneNumbers;
} 

您可以通过使用类元数据(例如指定注释)来进一步改善这一点:

@Target(ElementType.Type)
public @interface MappedTable {
    String tableName();
}

//apply the annotation to bean classes:
@MappedTable(tableName="CUSTOMERS")
public class Customer {}

这将允许您的findAll方法看起来像:

public <T> List<T> findAll(Class<T> entityClass){

    String sql = "SELECT * FROM " + entityClass
      .getAnnotation(MappedTable.class).tableName();

    return getJdbcTemplate().query(sql,
        new BeanPropertyRowMapper(entityClass));

    return phoneNumbers;
} 

实施findByXyZ会比较棘手,但是您可以使用类似的方法,该方法从呼叫者那里获取完整查询,或者使用其他基于注释的元数据。

注意,这种代码的复杂性增长非常快。这就是为什么考虑使用ORM工具而不是重新发明它们的一个好主意(以上只是针对简单案例的一种想法)。

答案 1 :(得分:1)

public <T> List<T> findAll(String sql, Class<T> clazz) {
   return getJdbcTemplate().query(sql, new BeanPropertyRowMapper(clazz));
}

然后致电

String sql = "SELECT * FROM CUSTOMER";
List<Customer> customers = findAll(sql, Customer.class);

String sql = "SELECT * FROM PHONE WHERE CUST_ID="+custId;
List<Phone> phoneNumbers = findAll(sql, Phone.class);

问题是您必须在调用该方法之前构造sql语句。

也许您想要一个类似于android sqldatabase的接口并在该方法中构造sql语句。

public <T> List<T> findAll(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy,  Class<T> clazz) {
    String sql = // construct sql statement
    return getJdbcTemplate().query(sql, new BeanPropertyRowMapper(clazz));
}

我对sql语句不熟悉,您可能会在Android SDK SQLiteQueryBuilder.buildQueryString(...)中找到一些东西。

如果您确实要返回单个项目而不是包含一个项目的列表,则需要另一种方法。

public <T> T findOne(String sql, Class<T> clazz) {
    // your sql statement should contains something like "limit 1"
    List<T> result = findAll(sql, clazz);
    return result.isEmpty() ? null : result.get(0);
}

如果需要一种方法,但需要为多个数据返回List<T>,为单个数据返回T。试试这个:

public <T> Object findAll(String sql, Class<T> clazz, bool one) {
    List<T> all = getJdbcTemplate().query(sql, new BeanPropertyRowMapper(clazz));
    return one ? all.get(0) : all;
}

但是我并不是真的建议这种方法。我认为没有必要返回单个项目,而不是返回包含单个项目的列表。

答案 2 :(得分:0)

您可以使用继承来实现这一目标

1)class Customer

2)class PhoneNumber extends Customer

3)class Address extends Customer

4)将方法声明为

public List<T> findPhoneNumbers(Customer customer){ 
if(customer instanceOf PhoneNumber) {sql ="get phone number query ...."}
else if(customer instanceOf Address) {sql ="get address query ...."}
else {sql = get customer query}
}

现在在调用方法(ServiceLayer)中,您可以传递适当的对象以选择查询并获取结果