当我们接触到数据库和Java连接的内容时,不得不提到的一点就是ORM(Object Relational Mapping)思想,翻译过来就是对象关系映射,简单来说就是表结构中的字段和类中的属性对应映射,实现一条数据库记录对应一个JavaBean对象
现在我们封装一个方法,使得我们传入一个对象实参之后,对应的数据库可以对应的增加一条数据 假设,我们有一个Trolley购物车类和AddUtil类
public class Trolley { private int productID; private int quantity; public Trolley(int productID, int quantity) { super(); this.productID = productID; this.quantity = quantity; } public int getProductID() { return productID; } public void setProductID(int productID) { this.productID = productID; } public int getQuantity() { return quantity; } public void setQuantity(int quantity) { this.quantity = quantity; } } public class AddUtil { //过滤方法为methodName的方法并放入List容器 private static List<Method> getMatchedMethods(Object obj, String methodName) { Method[] methods = obj.getClass().getDeclaredMethods(); List <Method> list = new ArrayList<>(); for (int index = 0; index < methods.length; index++) { if (methods[index].getName().indexOf(methodName) != -1) { //Class returnType = methods[index].getReturnType(); list.add(methods[index]); } } return list; } public static <T> void addData(T obj) { Connection conn = JDBCUtil.getConnection(); //假设现在需要插入String sql = "insert into trolley(md_mid,trolley_quantity) values (..,..,..)"; Map<String, Object> map = new HashMap<>(); Set<String> methodName = new HashSet<>();//用于存储方法的名称 Class clz = obj.getClass(); StringBuffer sql = new StringBuffer("insert into "); sql.append(clz.getSimpleName().toLowerCase()); sql.append("("); List<Method> methodList = getMatchedMethods(obj, "get"); Iterator<Method> it = methodList.iterator(); while(it.hasNext()) { Method method = it.next(); String attribute = method.getName().substring(3).toLowerCase();//从方法中获取属性名称 try { System.out.println(method.getName()); Object value = method.invoke(obj); System.out.println(value); map.put(attribute,value); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { e.printStackTrace(); } sql.append(attribute); sql.append(","); } sql.setCharAt(sql.lastIndexOf(","), ')');//实现了这一部分insert into trolley(md_mid,trolley_quantity) sql.append("values("); List<Method> methodList2 = getMatchedMethods(obj, "get"); Iterator<Method> it2 = methodList2.iterator(); while(it2.hasNext()) { Method method = it2.next(); String attribute = method.getName().substring(3).toLowerCase();//从方法中获取属性名称 Object value = map.get(attribute); sql.append(value); sql.append(","); } sql.setCharAt(sql.lastIndexOf(","), ')'); try { PreparedStatement ps = conn.prepareStatement(sql.toString()); System.out.println(sql.toString()); ps.executeUpdate(); JDBCUtil.realse(conn, ps); } catch (SQLException e) { e.printStackTrace(); } } public static void main(String[] args) { Trolley t = new Trolley(1100, 500); addData(t); } }但是细心的朋友发现,以上通过反射获取对象的get方法,并拆解get方法的全称,得到字段名(例如setProductID拆解之后可以获取ProductID字段),然后通过get方法获取属性的属性值也就是对应的数据库里面的字段值。 最后通过SQL语句将数据传输到数据库中。 但是上述方法有一个缺陷,就是我们的数据库的字段名称和Javabean类的属性值要一一对应才能实现对象到数据库的添加。当然我们也有相应的应对措施,例如约定一个规范,打个比方,类中的属性可以叫做 ProductID, 那么数据库中的字段名称可以命名为trolley_productid,或者product_id,这样我们可以新建一个方法,将类的属性名转为数据库的字段名称来进行调用。
但是!!最终极的方法是采用我们的==注解==方式,我们可以先定义一个注解来对这个Trolley类的属性做约束,并命名(类似于数据库的起别名)。(友情提示:如果对注解还不太熟的小伙伴可以先看我的另一篇讲解注解的文章 Marco’s Java 之【Annotation注解】)
@Target(value=ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Column { String value() default ""; }其次,我们可以将该注解放到我们需要注解的属性上方并命名
public class Trolley { @Column(value="md_mid") private int productID; @Column(value="trolley_quantity") private int quantity; public Trolley(int productID, int quantity) { super(); this.productID = productID; this.quantity = quantity; } public int getProductID() { return productID; } public void setProductID(int productID) { this.productID = productID; } public int getQuantity() { return quantity; } public void setQuantity(int quantity) { this.quantity = quantity; } }最后还是建一个AddUtil类封装相应的Add方法,将内容进行大换血!
public class AddUtil { //通过该方法获取该对象的注解value,以及这个属性的值 private static Map<String,Object> getAnnotations(Object obj) { Map<String,Object> map = new HashMap<>(); Field[] declaredFields = obj.getClass().getDeclaredFields(); for (Field field : declaredFields) { Column anno = field.getAnnotation(Column.class); if(anno!=null){ String attribute = anno.value(); try { field.setAccessible(true); Object value = field.get(obj); map.put(attribute, value); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } } return map; } public static <T> void addData(T obj) { Connection conn = JDBCUtil.getConnection(); Map<String, Object> map = getAnnotations(obj); StringBuffer sql = new StringBuffer("insert into "); Class clz = obj.getClass(); sql.append(clz.getSimpleName().toLowerCase()); sql.append("("); Set entryset = map.entrySet(); Iterator<Entry<String,Object>> it = entryset.iterator(); while(it.hasNext()) { Entry<String,Object> entry = it.next(); String attribute = entry.getKey(); sql.append(attribute); sql.append(","); } sql.setCharAt(sql.lastIndexOf(","), ')');//实现了这一部分insert into trolley(md_mid,trolley_quantity) sql.append("values("); Set entryset2 = map.entrySet(); Iterator<Entry<String,Object>> it2 = entryset2.iterator(); while(it2.hasNext()) { Entry<String,Object> entry = it2.next(); Object value = entry.getValue(); sql.append(value); sql.append(","); } sql.setCharAt(sql.lastIndexOf(","), ')');//实现了这一部分insert into trolley(md_mid,trolley_quantity) try { PreparedStatement ps = conn.prepareStatement(sql.toString()); ps.executeUpdate(); JDBCUtil.realse(conn, ps); } catch (SQLException e) { e.printStackTrace(); } public static void main(String[] args) { Trolley t = new Trolley(1100, 500); addData(t); } }实际开发中,我们可能会需要查询这一个数据库中的多个表,并且将表中的数据导出来==。 那么我们可以通过将查询的内容进行封装,在Java中创建一个实体类让类中的属性和数据库中的字段映射起来
public class ResultMetaTest{ public static <T> List<T> queryData(Class<T> clz, String sql, Object...param) { Connection conn = JDBCUtil.getConnection();//创建连接对象 try { PreparedStatement ps = conn.prepareStatement(sql);//创建操作数据库对象 //设置条件判断中的值 for(int i = 0; i < param.length; i++) { ps.setObject(i+1, param[i]); } ResultSet rs = ps.executeQuery();//获取结果集对象 ResultSetMetaData meta = rs.getMetaData();//获取数据集元信息 int column = meta.getColumnCount();//获取所搜寻的字段个数或者列数 List<T> list = new ArrayList<>();//创建用于储存构建出来的对象的容器 while(rs.next()) { Map<String,Object> map = new HashMap<>();//创建用于储存保存类的属性的map集合 for(int i = 0; i < column; i++) { String columnName = meta.getColumnLabel(i+1);//得到每一列的或者每一个字段的名称 Object obj = rs.getObject(columnName);//根据字段名称获取每一行对应的字段值 map.put(columnName, obj); } if(!map.isEmpty()) { T obj = clz.newInstance();//通过传入的类的Class对象创建这个类的对象 Set <Entry <String,Object>> entryset = map.entrySet(); for (Entry<String, Object> entry : entryset) { String atribute = entry.getKey();//提取这个类中的属性名称 Object value = entry.getValue();//提取这个类中属性的值 Field attribute = clz.getDeclaredField(atribute); attribute.setAccessible(true);//注意要设置权限为开放 attribute.set(obj, value);//通过反射给对象赋值 } list.add(obj);//将赋值完成的对象放入ArrayList容器中 } } JDBCUtil.realse(conn, ps, rs);//释放资源 return list; } catch (SQLException | InstantiationException | IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } return null; } public static void main(String[] args) throws Exception { String sql = "select u_uname as userName,u_pwd as password," + "u_tele as telePhone,u_realname as realName from userinfo where u_id = ?"; List<User> list = queryData(User.class,sql,1); System.out.println(list); } }