Java Spring/roo自定义查找器

Java Spring/roo自定义查找器,java,spring,spring-mvc,spring-roo,Java,Spring,Spring Mvc,Spring Roo,我想创建一个定制的finder(作为一名web开发老手,但在Java、Spring和Roo方面却是一个完全的新手) 下面的第一个方法来自我的“资产”视图控制器类。这是您第一次点击资产管理页面时发生的情况——它返回一个视图和一批当前活动的资产。它工作得很好: @RequestMapping("/assets") public ModelAndView listAssets() { ModelAndView mav = new ModelAndView(); mav.setViewN

我想创建一个定制的finder(作为一名web开发老手,但在Java、Spring和Roo方面却是一个完全的新手)

下面的第一个方法来自我的“资产”视图控制器类。这是您第一次点击资产管理页面时发生的情况——它返回一个视图和一批当前活动的资产。它工作得很好:

@RequestMapping("/assets")
public ModelAndView listAssets() {
    ModelAndView mav = new ModelAndView();
    mav.setViewName("admin/asset");
    Collection<com.myapp.model.Asset> assets = com.myapp.model.Asset.findAllAssets() ;
    mav.addObject("assets", assets);    
    return mav;
}
@RequestMapping(“/assets”)
公共模型和视图列表资产(){
ModelAndView mav=新ModelAndView();
mav.setViewName(“管理员/资产”);
集合资产=com.myapp.model.Asset.findAllAssets();
mav.addObject(“资产”,资产);
返回mav;
}
所以现在我想让一个“POST”请求发送到该URL,接受资产搜索表单的提交,该表单包含资产对象的几个关键属性的字段

(现在我正在我的视图控制器中对finder进行编码,我知道最终我会将其下推到model类。现在我只是为了方便起见在这里使用它。另外,我知道我不必给出对象的完全限定名,我已经将我的控制器命名为与它所对话的模型相同的名称,所以直到我重新命名为止。)我不知道,我正在努力解决这个问题。)

我从我生成的一些Roo Finder那里借用了一些代码,最终得到:

@RequestMapping(value = "/assets", method = RequestMethod.POST)
public ModelAndView searchAssets(
            @RequestParam("category") String category,
            @RequestParam("year") String year,
            @RequestParam("manufacturer") String manufacturer,
            @RequestParam("drive_type") String driveType,
            @RequestParam("subcategory") String subcategory,
            @RequestParam("serial") String serial,
            @RequestParam("listing_type") String listingType,
            @RequestParam("hours") String hours,
            @RequestParam("model") String model,
            @RequestParam("mileage") String mileage  ) {
    ModelAndView mav = new ModelAndView();
    mav.setViewName("admin/asset");


    EntityManager em = com.myapp.model.Asset.entityManager();
    TypedQuery<Asset> q = em.createQuery("SELECT o FROM Asset AS o ", Asset.class);
    Collection<Asset> assets =  q.getResultList();
    mav.addObject("assets", assets);

    return mav;
}
@RequestMapping(value=“/assets”,method=RequestMethod.POST)
公共模型和视图搜索资产(
@RequestParam(“类别”)字符串类别,
@RequestParam(“年”)字符串年份,
@RequestParam(“制造商”)字符串制造商,
@RequestParam(“驱动器类型”)字符串驱动器类型,
@RequestParam(“子类别”)字符串子类别,
@RequestParam(“串行”)字符串串行,
@RequestParam(“列表类型”)字符串listingType,
@RequestParam(“小时”)字符串小时,
@RequestParam(“模型”)字符串模型,
@RequestParam(“里程”)字符串(里程){
ModelAndView mav=新ModelAndView();
mav.setViewName(“管理员/资产”);
EntityManager em=com.myapp.model.Asset.EntityManager();
TypedQuery q=em.createQuery(“从资产中选择o作为o”,Asset.class);
集合资产=q.getResultList();
mav.addObject(“资产”,资产);
返回mav;
}
因此,问题是:

1) 有没有办法获取我的参数集合,而不是将它们烘焙到方法签名中?因为我有点讨厌这样

2) 有没有一种方法可以迭代我的参数并以这种方式生成查询字符串的WHERE子句?我不想对这里给我的领域有太多的了解,我需要能够处理这些领域,我大部分不会拥有所有领域。因此,如果有意义的话,我更愿意以迭代方式而不是声明方式构建查询

您将如何在这里构建select语句

编辑(解决方案):

@madth3为我指明了正确的方向。这是我最后得到的,我很自豪:

public static TypedQuery<Asset> findAssetsByWebRequest( WebRequest request) {

    ArrayList<String> wheres = new ArrayList<String>();

    Iterator<String> i = request.getParameterNames();

    while (i.hasNext()) {
        String fieldname = i.next();
        String value = request.getParameter(fieldname);

        if (value.length() == 0) {
            continue;
        }

        if (fieldname.equals("manufacturer") || fieldname.equals("model") ) {

            value = value.replace('*', '%');
            if (value.charAt(0) != '%') {
                value = "%" + value;
            }
            if (value.charAt(value.length() - 1) != '%') {
                value = value + "%";
            }
            wheres.add(" o." + fieldname + " LIKE '" + value + "'");
        }
        else if (fieldname.contains("min")) {
            fieldname = fieldname.replace("min", "").toLowerCase();
            wheres.add(" o." + fieldname + " >= '" + value + "' ");
        }
        else if (fieldname.contains("max")) {
            fieldname = fieldname.replace("max", "").toLowerCase();
            wheres.add(" o." + fieldname + " <= '" + value + "' ");

        }
        else {
            wheres.add(" o." + fieldname + " = '" + value + "' ");
        }
    }


    String query = "SELECT o FROM Asset AS o ";
    if (wheres.size() > 0) {
        query += " WHERE ";
        for (String clause: wheres) {
            query += clause + " AND "; 
        }
        query += " 1 = 1 ";
    }


    EntityManager em = Asset.entityManager();
    TypedQuery<Asset> q = em.createQuery(query, Asset.class);

    return q;
}
publicstatictypedqueryfindassetsbywebrequest(WebRequest请求){
ArrayList,其中s=新的ArrayList();
迭代器i=request.getParameterNames();
while(i.hasNext()){
字符串fieldname=i.next();
字符串值=request.getParameter(fieldname);
如果(value.length()==0){
继续;
}
if(fieldname.equals(“制造商”)| | fieldname.equals(“型号”)){
value=value.replace('*','%');
if(value.charAt(0)!=“%”{
value=“%”+值;
}
if(value.charAt(value.length()-1)!=“%”{
值=值+“%”;
}
式中。添加(“o.”+fieldname+“LIKE”“+value+”);
}
else if(fieldname.contains(“min”)){
fieldname=fieldname.replace(“min”,”).toLowerCase();
其中。添加(“o.”+fieldname+“>=”“+value+””);
}
else if(fieldname.contains(“max”)){
fieldname=fieldname.replace(“max”,”).toLowerCase();

其中,add(“o.”+fieldname+”Spring roo可以为您生成查找程序:

类型:


finder list
将列出所有具有一个属性的finder,您可以使用可选参数设置属性的数量

好吧,按照传统方式。。。 Java中的Servlets标准定义了对象请求,其中有带参数的映射(散列、字典),所以您可以像这样访问它们

public ModelAndView searchAssets(HttpRequest request) {
    StringBuilder builder = new StringBuilder();
    for (String param : request.getParameterNames()) {
        value = request.getParameter(param);
        builder.append(param);
        builder.append("="); // or LIKE
        builder.append("\'" + value "\'");
        builder.append(" AND ");
    }
    // deleting the last " AND "
    builder.delete(builder.length-5, builder.length);
    // In the entity create a method that executes a query with the string
    // If the parameter names are column names then you'd have to use a nativeQuery
    // You'd have to look it up in JPA
   List<Asset> list = Asset.search(builder.toString());
   // put the list in the ModelAndView
}
公共模型和视图搜索资产(HttpRequest请求){
StringBuilder=新的StringBuilder();
for(字符串参数:request.getParameterNames()){
value=request.getParameter(param);
builder.append(参数);
builder.append(“=”;//或类似
builder.append(“\'”+值“\'”);
建造商。附加(“和”);
}
//删除最后一个“和”
builder.delete(builder.length-5,builder.length);
//在实体中,创建使用字符串执行查询的方法
//如果参数名是列名,则必须使用nativeQuery
//你得在JPA上查一下
List=Asset.search(builder.toString());
//将列表放在ModelAndView中
}

我发表了评论,但我更愿意在回答中解释我的方法:


我认为最好像Raloh下面所说的那样(使用Roo生成的代码),使用POJO作为参数而不是WebRequest来创建一个自定义查找器,这样就不会与MVC产生依赖关系

尝试创建一个POJO,例如AssetFilter,其中包含要在finder中使用的属性

public static TypedQuery<Asset> findAssetsByFilter(AssetFilter filter) {
    If (filter.getManufacturer()!=null) where.append(" AND ...")
}
publicstatictypedqueryfindassetsbyfilter(AssetFilter过滤器){
If(filter.getManufacturer()!=null)where.append(“AND…”)
}
控制器将根据请求创建POJO过滤器,您可以在任何地方使用该查找器,甚至可以为其创建集成测试。

没错,
public static TypedQuery<Asset> findAssetsByFilter(AssetFilter filter) {
    If (filter.getManufacturer()!=null) where.append(" AND ...")
}