# Problem beim Erstellen einer Query



## markai (20. Jun 2012)

Ich hätte gerne eine Query die mir Products sucht die einen bestimmten String im Namen haben. Also wenn der Benutzer "schraube" eingibt soll eine Liste zurückgegeben werden mit Records die im Namen "schraube" enthalten. (Schrauben, Schraubenschlüssel...). Dazu habe ich folgendes gemacht:


```
@Entity
@NamedQueries({
    @NamedQuery(name="findByName",
        query="select p from Product p where lower(p.name) like '%:name%'")
})
public class Product implements Serializable, Comparable<Product> {
...
```

:name ist der Parameter den der Benutzer eingibt.

In meiner ProductFacade mach ich:


```
public List<Product> findProduct(String product) {
        return em.createNamedQuery("findByName", Product.class).setParameter("name", product).getResultList();
    }
```

Leider bekomme ich immer diese Exception:


```
...
Caused by: java.lang.IllegalArgumentException: You have attempted to set a parameter value using a name of name that does not exist in the query string select p from Product p where lower(p.name) like '%:name%'.
```

Bin mir nicht sicher was mein Netbeans mir damit sagen will...


----------



## nillehammer (20. Jun 2012)

Probier mal folgendes:

```
@Entity
@NamedQueries({
    @NamedQuery(name="findByName",
        query="select p from Product p where lower(p.name) like :searchPattern")
})
public class Product implements Serializable, Comparable<Product> {
..:
```


```
public List<Product> findProduct(String product) {

        final String searchPattern = 
           new ToStringBuilder().append('%').append(product).append('%').toString();

        return em.createNamedQuery("findByName", Product.class).setParameter("searchPattern", searchPattern).getResultList();
    }
```

Ich glaube, dass literale in einer JPQL-Query nicht mit dynamischen Parametern gemischt werden können. Sowas 
	
	
	
	





```
'%:name%'
```
 geht darum nicht.


----------



## JimPanse (20. Jun 2012)

So sollte es funktionieren...


```
@Entity
@NamedQueries({
    @NamedQuery(name="findByName",
        query="select p from Product p where lower(p.name) like :name")
})
public class Product implements Serializable, Comparable<Product> {
...
```



```
public List<Product> findProduct(String product) {
        return em.createNamedQuery("findByName", Product.class).setParameter("name", product.toLowerCase()+"%").getResultList();
    }
```


----------



## markai (22. Jun 2012)

Vielen Dank euch beiden. Hat funktioniert! Jetzt habe ich noch ein weiteres Problem: Mein Product besteht aus mehreren Teilen. Nun möchte ich dass der Benutzer Produkte nach Teilen suchen kann.
Zwischen Product und Part besteht eine n:m Beziehung. Eigentlich brauche ich ja nur die Zwischentabelle Product_Part anzuschauen um herauszufinden welches Product welche Parts enthält. Allerdings kann ich mit jpa nicht direkt auf diese Zwischentabelle zugreifen (unknown Entity).

Hier noch der Code wie ich es momentan mache, um zu zeigen was ich vorhab:


```
public void searchByParts() {
        List<Product> result = new ArrayList<>();
        List<Part> selectedParts = partController.getAcSelectedParts();
        for (Product product : getAllProducts) {
            if (Arrays.asList(selectedParts).containsAll(product.getParts())) {
                result.add(product);
            }
        }
        this.resultList = result;
```


----------



## Spitfire777 (22. Jun 2012)

Denke ich zu einfach, oder tut es das hier nicht auch?


```
@Entity
@NamedQueries({
    @NamedQuery(name="findByName",
        query="select p from Product p where lower(p.name) like '%'||:name||'%'")
})
public class Product implements Serializable, Comparable<Product> {
...
```

Weil nur bei einem '%:name%' wird :name als Text gewertet und nicht als Parameter. Daher hab ich das bisher immer mit dem Konkatenationsoperator || einfach verbunden.


----------



## nillehammer (22. Jun 2012)

> Vielen Dank euch beiden. Hat funktioniert! Jetzt habe ich noch ein weiteres Problem: Mein Product besteht aus mehreren Teilen. Nun möchte ich dass der Benutzer Produkte nach Teilen suchen kann.
> Zwischen Product und Part besteht eine n:m Beziehung. Eigentlich brauche ich ja nur die Zwischentabelle Product_Part anzuschauen um herauszufinden welches Product welche Parts enthält. Allerdings kann ich mit jpa nicht direkt auf diese Zwischentabelle zugreifen (unknown Entity).


Habe es leider nicht ausprobiert, weil es mir zu viel Aufwand war, dafür jetzt ein JPA-Projekt aufzusetzen, aber die Schlüsselworte 
	
	
	
	





```
IN
```
, 
	
	
	
	





```
MEMBER OF
```
 oder 
	
	
	
	





```
ALL
```
 müssten Dich zum Ziel führen. Vielleicht klappt sogar schon das:

```
@NamedQuery(name="findByParts", query="SELECT p FROM Product p WHERE :parts IN p.parts")
```


----------



## markai (23. Jun 2012)

Kann sein dass ich einen Denkfehler hab, aber ich glaub nicht dass das funktionieren kann. Meine Product Tabelle hat keine Parts Spalte. Muss ich die beiden Tabellen nicht über die Zwischentabelle joinen? Da dies mein erstes mal mit JPA ist hab ich keine Ahnung wie ich zu meinem Ergebnis kommen soll... ;(


----------



## nillehammer (23. Jun 2012)

> Meine Product Tabelle hat keine Parts Spalte. Muss ich die beiden Tabellen nicht über die Zwischentabelle joinen


In plain SQL müsstest Du das. In JPA allerdings navigierst Du über die Felder, die Du in Deinen Objekten hast. Dass Product eine Collection (List? Set?) von Parts hat, habe ich aus dem Code 
	
	
	
	





```
product.getParts()
```
 in einem Deiner letzten Posts geschlossen.


> Da dies mein erstes mal mit JPA ist hab ich keine Ahnung wie ich zu meinem Ergebnis kommen soll...


Ja, es hat bei mir auch mehr als ein Jahr gedauert, bis ich mich vom SQL-/Datenbankdenken gelöst hatte und bei den Relationen in der Objektwelt gedacht hatte.


----------

