一、问题描述
问题描述:
在CRUD的项目中使用JdbcTemplate操作数据库时,在dao层我们会发现这样一个问题,代码量重复且繁杂,现在如下类型参照表:

在对他进行操作时,会有以下的代码:
1.实体类(model层)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
|
@Component public class Damage_type_stable {
private int damage_type_sid; private String damage_type_sname; private String damage_type_shape; private String damage_type_calcu; private int damage_type_fid;
public int getDamage_type_sid() { return damage_type_sid; }
public void setDamage_type_sid(int damage_type_sid) { this.damage_type_sid = damage_type_sid; }
public String getDamage_type_sname() { return damage_type_sname; }
public void setDamage_type_sname(String damage_type_sname) { this.damage_type_sname = damage_type_sname; }
public String getDamage_type_shape() { return damage_type_shape; }
public void setDamage_type_shape(String damage_type_shape) { this.damage_type_shape = damage_type_shape; }
public String getDamage_type_calcu() { return damage_type_calcu; }
public void setDamage_type_calcu(String damage_type_calcu) { this.damage_type_calcu = damage_type_calcu; }
public int getDamage_type_fid() { return damage_type_fid; }
public void setDamage_type_fid(int damage_type_fid) { this.damage_type_fid = damage_type_fid; }
@Override public String toString() { return "Damage_type_stable{" + "damage_type_sid=" + damage_type_sid + ", damage_type_sname='" + damage_type_sname + '\'' + ", damage_type_shape='" + damage_type_shape + '\'' + ", damage_type_calcu='" + damage_type_calcu + '\'' + ", damage_type_fid=" + damage_type_fid + '}'; } }
|
2、持久化层(dao层)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| ** * 损坏类型子参照表数据库操作:持久化层 */ @Repository public class DamageTypeStableDao {
@Autowired private JdbcTemplate jdbcTemplate;
public List<Damage_type_stable> findAll(){ try { String sql=""; List<Damage_type_stable> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Damage_type_stable>(Damage_type_stable.class)); return query; } catch (DataAccessException e) { e.printStackTrace(); return null; } }
public void add(Damage_type_stable damage_type_stable){ String sql=""; jdbcTemplate.update(sql,damage_type_stable.getDamage_type_sid(),damage_type_stable.getDamage_type_sname(),damage_type_stable.getDamage_type_shape(),damage_type_stable.getDamage_type_calcu(),damage_type_stable.getDamage_type_fid()); }
public void delete(int id)throws DataAccessException{ String sql=""; jdbcTemplate.update(sql,id); }
public void change(Damage_type_stable damage_type_stable){ String sql=""; jdbcTemplate.update(sql,damage_type_stable.getDamage_type_sname(),damage_type_stable.getDamage_type_shape(),damage_type_stable.getDamage_type_calcu(),damage_type_stable.getDamage_type_fid(),damage_type_stable.getDamage_type_sid()); } }
|
我们会很容易的发现,在使用JdbcTemplate的update和query方法进行自动封装时对可变参数的传入重复且繁杂,假如我们的实体类有几十,甚至几百个属性呢…..
二、解决办法
解决思路(以add方法为例):
在JdbcTemplate中,提供了update方法的另一种重载方式:update(sql,Object []);,可以传入一个Object类的数组,按顺序依次封装。既然如此,我们就可以通过Java的反射机制,写一个工具方法,以Object类对象为参数,通过获取到对象中的所有get方法,将get到的返回值封装在一个数组里,使用上述update(sql,Object []);,进行数据库操作。实现自动封装update方法的可变参数。
1、建库,并编写实体类(以Users类为示例)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
|
@Component public class Users {
private String username; private String pasword;
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getPasword() { return pasword; }
public void setPasword(String pasword) { this.pasword = pasword; }
@Override public String toString() { return "Users{" + "username='" + username + '\'' + ", pasword='" + pasword + '\'' + '}'; } }
|
2、获取到类对象所有的get方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
public List<Method> getAllReadMethod(Object object){ List<Method> method=new ArrayList<Method>(); Class<? extends Object> testClass = object.getClass(); Field[] fields = object.getClass().getDeclaredFields(); for (Field field : fields) { try { PropertyDescriptor pd = new PropertyDescriptor(field.getName(), testClass); Method getMethod = pd.getReadMethod(); method.add(getMethod); } catch (IntrospectionException e) { e.printStackTrace(); } } return method; }
|
3、得到所有get方法的返回值,并封装进Object数组中,然后返回
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
public Object[] getAllMethodName(Object object){ List<Method> allReadMethod = getAllReadMethod(object); Object [] values=new Object[allReadMethod.size()]; int i=0; for(Method e:allReadMethod){ try { Object invoke = e.invoke(object); String s = invoke.toString(); values[i]=s; i++; } catch (IllegalAccessException e1) { e1.printStackTrace(); } catch (InvocationTargetException e1) { e1.printStackTrace(); } } return values; }
|
4、编写add方法
1 2 3 4 5 6 7 8 9 10
|
public void add(String sql,Object object) { Object[] allMethodName = getAllMethodName(object); jdbcTemplate.update(sql,allMethodName); }
|
5、测试
1 2 3 4 5 6 7 8 9
| @Test public void test04(){ Users user = new Users(); user.setUsername("abcde"); user.setPasword("12345"); UserDao bean = ioc.getBean(UserDao.class); bean.add(user); }
|
6、测试结果

附完整代码(add,delete,change,findAll方法):
ClassUtils.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
| @Component public class ClassUtils {
@Autowired private JdbcTemplate jdbcTemplate;
public List<Method> getAllReadMethod(Object object){ List<Method> method=new ArrayList<Method>(); Class<? extends Object> testClass = object.getClass(); Field[] fields = object.getClass().getDeclaredFields(); for (Field field : fields) { try { PropertyDescriptor pd = new PropertyDescriptor(field.getName(), testClass); Method getMethod = pd.getReadMethod(); method.add(getMethod); } catch (IntrospectionException e) { e.printStackTrace(); } } return method; }
public Object[] getAllMethodName(Object object){ List<Method> allReadMethod = getAllReadMethod(object); Object [] values=new Object[allReadMethod.size()]; int i=0; for(Method e:allReadMethod){ try { Object invoke = e.invoke(object); String s = invoke.toString();
values[i]=s; i++; } catch (IllegalAccessException e1) { e1.printStackTrace(); } catch (InvocationTargetException e1) { e1.printStackTrace(); } } return values; }
public Object[] getAllMethodNameAdd(Object object){ List<Method> allReadMethod = getAllReadMethod(object); Object [] values=new Object[allReadMethod.size()-1]; int j=0; for(int i=1;i<allReadMethod.size();i++){ try { Object invoke = allReadMethod.get(i).invoke(object); String s = invoke.toString(); values[j]=s; j++; } catch (IllegalAccessException e1) { e1.printStackTrace(); } catch (InvocationTargetException e1) { e1.printStackTrace(); } } return values; }
public List<?> findAll(String sql,Object object){ try { List<?> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(object.getClass())); return query; } catch (DataAccessException e) { e.printStackTrace(); return null; } }
public void add(String sql,Object object) { Object[] allMethodName = getAllMethodNameAdd(object); jdbcTemplate.update(sql,allMethodName); }
public void delete(String sql,int id){ jdbcTemplate.update(sql,id); }
public void delete(String sql,String id){ jdbcTemplate.update(sql,id); }
public void change(String sql,Object object){ Object[] allMethodName = getAllMethodName(object); Object o=allMethodName[0]; for(int i=0;i<allMethodName.length-1;i++){ allMethodName[i]=allMethodName[i+1]; } allMethodName[allMethodName.length-1]=o; jdbcTemplate.update(sql,allMethodName); }
public Object messageBackLook(String sql,int id,Object object){ try { Object o = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(object.getClass()), id); return o; } catch (DataAccessException e) { e.printStackTrace(); return null; } }
public Object messageBackLook(String sql,String id,Object object){ try { Object o = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(object.getClass()), id);
return o; } catch (DataAccessException e) { e.printStackTrace(); return null; } }
}
|
finish!