Spring / roo定制查找器 [英] Spring/roo custom finder

查看:79
本文介绍了Spring / roo定制查找器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个自定义查找程序(作为Web开发资深人员,但在Java,Spring和AND Roo中是一个完整的第一个计时器)。

I want to create a custom finder (being a web development veteran but a complete first-timer at Java, Spring, AND Roo).

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

The first method below is from my "Asset" view controller class. It's what happens on your first hit to the asset administration page--it comes back with a view and a batch of the currently active assets. It works fine:

@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;
}

所以现在我想对该URL发出POST请求接受提交资产搜索表单,其中包含Asset对象的几个关键属性的字段。

So now I want to have a "POST" request to that URL accept the submission of the asset search form, which contains fields for several of the key properties of the Asset object.

(现在我在视图控制器中对该查找器进行编码,我知道最终我会把它推到模型类。现在我只是为了方便而在这里工作。而且,我知道我不必给出对象的完全限定名称,我我的控制器名称与它正在谈论的模型同名,所以在我解决之前,我正在解决它。)

(Right now I'm coding that finder in my view controller, and I know ultimately I'll want to push that down to the model class. For now I'm just working it here for convenience sake. Also, I know I don't have to give the fully qualified name of the object, I've newbishly named my controller the same name as the model it's talking to, so until I sort that out, I'm working around it.)

我借了我生成的一些Roo查找器的一些代码,结果是:

I've borrowed some code from some Roo finders I generated, and ended up with:

@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;
}

所以问题是:

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

1) Is there a way to get a collection of my parameters, rather than baking them into the method signature? Because I sort of hate that.

2)有没有办法迭代我的参数并以这种方式生成查询字符串的WHERE子句?我不想太了解我在这里所给的领域 - 而且我需要能够解决这个问题,因为我大多数都不会拥有这些领域。所以我更愿意只是迭代地构建我的查询而不是声明性地构建我的查询,如果这是有道理的。

2) Is there a way to iterate over my parameters and generate the WHERE clause of my query string that way? I'd like to not have to know much about the fields I'm being given here--and I need to be able to handle that I mostly won't have all of them. So I'd prefer to just build my query iteratively rather than declaratively, if that makes sense.

您将如何在此处构建select语句?

How would you go about building the select statement here?

编辑(解决方案):

@ madth3在这里指出了正确的方向。这就是我最终得到的结果,我非常自豪:

@madth3 pointed me in the right direction here. Here's what I ended up with, which I'm pretty proud of:

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;
}

显然需要参数化以避免SQL注入攻击,但它很酷它(几乎)不必知道有关给定数据的任何信息,它只是从它给出的字段中组装一个查询。它确实需要知道它正在做哪些字段 - 哪些字段是喜欢而不是等于,如何处理定义范围的min和max字段等等。但这并不是那么糟糕。

It obviously needs to be parameterized to avoid SQL injection attack, but it's cool that it (nearly) doesn't have to know anything about the data being given it, that it'll just assemble a query from the fields it was given. It does need to know which fields it's doing what with--which fields are "like" versus "equals", how to handle "min" and "max" fields that define a range, etc. But that's not so bad.

推荐答案

好吧,采用老式的方式...
Java中的Servlets标准定义了对象Request,其中有Map(哈希,字典)与参数,所以你可以访问它们像

Well, going the old fashioned way... The Servlets standard in Java defines object Request where there is Map (hash, dictionary) with the parameters, so you could access them something like

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
}

这篇关于Spring / roo定制查找器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆