• 周五. 4月 26th, 2024

5G编程聚合网

5G时代下一个聚合的编程学习网

热门标签

hibernate:通用DAO+动态生成HQL语句

admin

11月 28, 2021

写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了。

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注