写WEB项目写的多了,感觉DAO层的代码太相似了,几乎写DAO的时候只要写好了一个类的DAO后另外几个类的DAO都是ctrl+C ctrl+V然后修改修改其中的参数后就完工了。前段时间无聊就去研究了下java的反射结果动态生成HQL语句的工具类就这样被我写出来了,贴上源码
public class BaseDao { protected Session session; Transaction transaction; /** * 打开session并且创建事物 */ protected void open(){ if(session == null || !session.isOpen()){ session = HibernateSessionFactory.getSession(); transaction = session.beginTransaction(); } } /** * 关闭session并且提交事物 */ protected void close(){ if(session!=null){ transaction.commit(); session.close(); } } }
/** * 通用DAO接口 * @author Administrator * */ public interface InCommonDao { public void add(Object o); public void delete(Object o); public void delete(long id,Class c); public void update(Object o); public Object query(long id,Class c); //public Object query(Object o); public List query(String sql , List condition); }
/** * 通用DAO接口实现 * @author Administrator * */ public class CommonDaoImpl extends BaseDao implements InCommonDao { @Override public void add(Object o) { // TODO Auto-generated method stub this.open(); this.session.save(o); this.close(); } @Override public void delete(Object o) { // TODO Auto-generated method stub this.open(); this.session.delete(o); this.close(); } @Override public void delete(long id, Class c) { // TODO Auto-generated method stub this.open(); Object o = this.query(id, c); session.delete(o); this.close(); } @Override public void update(Object o) { // TODO Auto-generated method stub this.open(); session.clear(); this.session.saveOrUpdate(o); this.close(); } @Override public Object query(long id, Class c) { // TODO Auto-generated method stub this.open(); return session.get(c, id); } @Override public List query(String sql, List condition) { // TODO Auto-generated method stub this.open(); Query query = session.createQuery(sql); if (condition != null && condition.size() > 0) { for (int i = 0; i < condition.size(); i++) { query.setParameter(i, condition.get(i)); } } return query.list(); } public Object query(String sql, List condition,Boolean bool) { // TODO Auto-generated method stub this.open(); Query query = session.createQuery(sql); if (condition != null && condition.size() > 0) { for (int i = 0; i < condition.size(); i++) { query.setParameter(i, condition.get(i)); //System.out.println(condition.get(i)); } } return query.uniqueResult(); } /* * @Override public Object query(Object o) { // TODO Auto-generated method * stub this.open(); session.refresh(o); return o; this.open(); return * query(((User)o).getId()); } */ }
/** * 给对象做反射并且定于返回HQL语句方法的抽象类 * @author Administrator * */ public abstract class SQLSuper { protected StringBuffer SQL; public StringBuffer getSQL() { return SQL; } public void setSQL(StringBuffer sQL) { SQL = sQL; } public abstract String getSQL(Object obj , List condition,OrderBy orderBy); /** * 返回所有类的名字 * @param tables * @return List<String> */ protected List<String> getClassNames(List<?> tables){ List<String> classNames = null; if(tables != null && tables.size()!=0){ classNames = new ArrayList<String>(); for(Object obj : tables){ /*if(obj instanceof Content){ classNames.add(obj.getClass().getSimpleName()); }else if(obj instanceof Member){ classNames.add(obj.getClass().getSimpleName()); }else if(obj instanceof NewsInfo){ classNames.add(obj.getClass().getSimpleName()); }else if(obj instanceof Topic){ classNames.add(obj.getClass().getSimpleName()); }*/ classNames.add(obj.getClass().getSimpleName()); } } return classNames; } /** * 返回类的名字 * @param table * @return */ protected String getClassName(Object table){ String className = null; if(table != null){ /*if(table instanceof Content){ className=table.getClass().getSimpleName(); }else if(table instanceof Member){ className=table.getClass().getSimpleName(); }else if(table instanceof NewsInfo){ className=table.getClass().getSimpleName(); }else if(table instanceof Topic){ className=table.getClass().getSimpleName(); }*/ className=table.getClass().getSimpleName(); } return className; } /** * 给传入的对象做反射 * @param o * @return */ protected Class<?> getClassReverberate(Object o){ String ClassName = o.getClass().getName(); Class<?> demo = null; try { demo = Class.forName(ClassName); } catch (Exception e) { e.printStackTrace(); } return demo; } /** * 返回类中的所有属性 * @param o * @return List<String> */ protected List<String> getClassPropertyName(Object o) { Class<?> demo = this.getClassReverberate(o); List<String> classPropertyNames = null; Field[] field = demo.getDeclaredFields(); classPropertyNames = new ArrayList<String>(); for (int i = 0; i < field.length; i++) { classPropertyNames.add(field[i].getName()); } return classPropertyNames; } /** * 使用反射调用对象的get方法 * @param obj * 操作的对象 * @param att * 操作的属性 * */ public Object getter(Object obj, String att) { try { Method method = obj.getClass().getMethod("get" + firstLower(att)); return method.invoke(obj); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 使用反射调用对象的set方法 * @param obj * 操作的对象 * @param att * 操作的属性 * @param value * 设置的值 * @param type * 参数的属性 * */ public void setter(Object obj, String att, Object value, Class<?> type) { try { Method method = obj.getClass().getMethod("set" + firstLower(att), type); method.invoke(obj, value); } catch (Exception e) { e.printStackTrace(); } } /** * 给setter()的操作的属性首字母大写 * @param att setter()操作的属性 * @return */ protected String firstLower(String att) { StringBuffer sb = new StringBuffer(); sb.append(att.substring(0,1).toUpperCase()); sb.append(att.substring(1, att.length())); return sb.toString(); } }
/** * 返回HQL语句的工具类,实现SQLSuper抽象类 * @author Administrator * */ public class SQLUtil extends SQLSuper { @Override public String getSQL(Object obj , List condition ,OrderBy orderBy) { /*if(condition == null){ condition = new ArrayList(); }*/ StringBuffer sb = new StringBuffer(); sb.append(" from "); sb.append(this.getClassName(obj)); //sb.append(" where "); StringBuffer conditionSQL = new StringBuffer(); List<String> classPropertyName = this.getClassPropertyName(obj); for (int i = 0; i < classPropertyName.size(); i++) { Object gett = this.getter(obj, classPropertyName.get(i).toString()); if (gett == null || gett.equals("-1") || gett.toString().equals("-1")) { continue; } /*if (i > 0) { conditionSQL.append(" and "); }*/ if(gett instanceof List){ //Object[] array = (Object[])gett; //Array array = (Array) gett; List array = (List) gett; if(array.size()==1){ conditionSQL.append(classPropertyName.get(i).replace('_', '.')+" > ?"); condition.add(array.get(0)); }else if(array.size()==2){ conditionSQL.append(classPropertyName.get(i).replace('_', '.')+" between ? and ?"); condition.add(array.get(0)); condition.add(array.get(1)); } }else{ conditionSQL.append(classPropertyName.get(i).replace('_', '.')+" = ? "); condition.add(gett); } conditionSQL.append(" and "); } if(conditionSQL.toString().length()>0){ sb.append(" where "); sb.append(conditionSQL.toString()); sb.append(" 1 = 1 "); } sb.append(" order by "); sb.append(orderBy.getColumn()); sb.append(" "); sb.append(orderBy.getType()); System.out.println(sb.toString()); for (Object o : condition) { System.out.println(o); } return sb.toString(); } /*public static void main(String[] args) { House house = new House(); house.setId(2); house.setStreet_id(3); SQLUtil sql = new SQLUtil(); System.out.println(sql.getSQL(house)); }*/ }
/** * HTL语句的排序属性类 * @author Administrator * */ public class OrderBy { private String column = "id"; /** * desc or asc */ private String type = "asc"; public String getColumn() { return column; } public void setColumn(String column) { this.column = column; } public String getType() { return type; } public void setType(String type) { this.type = type; } }
动态生成HQL语句是通过反射进行的,那么就需要传入实体类了吧。但是Hibernate映射的实体类确实不能用,需要进行修改
修改的示例:
hibernate的映射实体类
public class House implements java.io.Serializable { // Fields private Long id; private User user; private Type type; private Street street; private String title; private String descrition; private Date ployDate; private Double price; private String contact; private Long area; // Constructors /** default constructor */ public House() { } /** full constructor */ public House(User user, Type type, Street street, String title, String descrition, Date ployDate, Double price, String contact, Long area) { this.user = user; this.type = type; this.street = street; this.title = title; this.descrition = descrition; this.ployDate = ployDate; this.price = price; this.contact = contact; this.area = area; } // Property accessors public Long getId() { return this.id; } public void setId(Long id) { this.id = id; } public User getUser() { return this.user; } public void setUser(User user) { this.user = user; } public Type getType() { return this.type; } public void setType(Type type) { this.type = type; } public Street getStreet() { return this.street; } public void setStreet(Street street) { this.street = street; } public String getTitle() { return this.title; } public void setTitle(String title) { this.title = title; } public String getDescrition() { return this.descrition; } public void setDescrition(String descrition) { this.descrition = descrition; } public Date getPloyDate() { return this.ployDate; } public void setPloyDate(Date ployDate) { this.ployDate = ployDate; } public Double getPrice() { return this.price; } public void setPrice(Double price) { this.price = price; } public String getContact() { return this.contact; } public void setContact(String contact) { this.contact = contact; } public Long getArea() { return this.area; } public void setArea(Long area) { this.area = area; } }
修改后用来反射生成where条件的实体类
public class House { private long id = -1; private long user_id = -1; private long type_id = -1; private long street_id = -1; private String title; // private String descrition; // private Date ployDate; /** * price[0] 为开始价格 * price[1] 为结束价格 */ private List price; /** * area[0] 为开始大小 * area[1] 为结束大小 */ private List area; public long getId() { return id; } public void setId(long id) { this.id = id; } public long getUser_id() { return user_id; } public void setUser_id(long user_id) { this.user_id = user_id; } public List getPrice() { return price; } public void setPrice(List price) { this.price = price; } public List getArea() { return area; } public void setArea(List area) { this.area = area; } public long getType_id() { return type_id; } public void setType_id(long type_id) { this.type_id = type_id; } public long getStreet_id() { return street_id; } public void setStreet_id(long street_id) { this.street_id = street_id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } }
下面就贴上一个示例,这个示例是从项目中的BIZ层拿出来的。
public class HouseBizImpl implements InHouseBiz { CommonDaoImpl commonDaoImpl = new CommonDaoImpl(); @Override public List<House> getAllHouses(String price,String street,String housetype,String floorage,String title) { // TODO Auto-generated method stub com.vincent.hoseRental.entity.condition.House house = new com.vincent.hoseRental.entity.condition.House(); if(price!=null && !price.trim().equals("")){ String[] ps = price.split("-"); List dps = new ArrayList(2); dps.add(Double.parseDouble(ps[0])); try{ dps.add(Double.parseDouble(ps[1])); }catch (Exception e) { } house.setPrice(dps); } if(street!=null && ! street.trim().equals("")){ house.setStreet_id(Long.parseLong(street)); } if(housetype!=null && ! housetype.trim().equals("")){ house.setType_id(Long.parseLong(housetype)); } if(floorage!=null && ! floorage.trim().equals("")){ String[] ps = floorage.split("-"); List dps = new ArrayList(2); dps.add(Long.parseLong(ps[0])); try{ dps.add(Long.parseLong(ps[1])); }catch (Exception e) { } house.setArea(dps); } if(title!=null && ! title.trim().equals("")){ house.setTitle(title); } SQLUtil sqlUtil = new SQLUtil(); List condition = new ArrayList(); OrderBy orderBy = new OrderBy(); orderBy.setColumn("ploy_date"); orderBy.setType("desc"); String sql = sqlUtil.getSQL(house, condition,orderBy); return commonDaoImpl.query(sql, condition); //return houseDao.queryHouse(); } @Override public House getHouseById(int id) { // TODO Auto-generated method stub return (House)commonDaoImpl.query(id, House.class); } @Override public void deleteHouse(int id) { // TODO Auto-generated method stub commonDaoImpl.delete(id, House.class); } @Override public void addHouse(String title, long houseType, long floorage, double price, long district, long street, String contact, String descrition,User user) { // TODO Auto-generated method stub House house = new House(); house.setArea(floorage); house.setContact(contact); house.setDescrition(descrition); house.setPloyDate(new Date()); house.setPrice(price); Street s = new Street(street); s.setDistrict(new District(district)); house.setStreet(s); house.setTitle(title); house.setType(new Type(houseType)); house.setUser(user); commonDaoImpl.add(house); } @Override public void updateHouse(long id,String title, long houseType, long floorage, double price, long district, long street, String contact, String descrition,User user) { House house = new House(); house.setId(id); house.setArea(floorage); house.setContact(contact); house.setDescrition(descrition); house.setPloyDate(new Date()); house.setPrice(price); Street s = new Street(street); s.setDistrict(new District(district)); house.setStreet(s); house.setTitle(title); house.setType(new Type(houseType)); house.setUser(user); commonDaoImpl.update(house); } }
其实这里还缺少一个分组的条件,既然是Hibernate那就很简单了,BIZ层将生成好的HQL语句和条件给DAO层的时候附带一个分组类的对象过去,在query对象中作下分组就OK了。