[JPA/JPQL] IP-Adressen ordnen.

S

Smoothi

Gast
Hallo ;),

wie kann ich mittels JPQL IP-Adressen richtig ordnen, ohne jede Zahl in eine extra Spalte zu schreiben.

ORDER BY ipAddress.ip <<< das gibt logischerweise die falsche Sortierung aus.

also wenn ich 127.0.0.2 und 127.0.0.12 hab, wird es damit so geordnet:
1. 127.0.0.12
2. 127.0.0.2

Natürlich soll es umgekehrt sein. Leider bietet mir JPQL nicht allzuviele Möglichkeiten :/

lg
 
N

nillehammer

Gast
Nein, das geht nicht. Sortierung erfolgt hier "alphabetisch". Das kann man nicht ändern. Zwei Möglichkeiten, das zu umgehen:
- Änder das Datenmodell (die Idee hattest Du ja auch schon)
- Hol Dir die IPs, die Du sortieren wills nach Java und arbeite mit einem selbst gestrickten Comparator für die Sortierung.
 
S

Smoothi

Gast
schade eigentlich. In SQL wäre es kein Problem. :/

Das Datenmodell wollte ich nicht unbedingt ändern, da ich dann bei jeder Abfrage alle 4 Elemente benötige. Wäre aber wohl meine letzte Ausweglösung.

Was genau meinst du mit selbstgestrickter Comparator? Steh gerade aufm Schlauch. ;)
 
N

nillehammer

Gast
Code:
- Du holst Dir die unsortierten Daten (ich nehmen mal an Strings) aus der Datenbank in eine List.
- Du implementierst einen Comparator, der für die gewünschte Reihenfolge sorgt
  (http://download.oracle.com/javase/6/docs/api/java/util/Comparator.html)
  (evtl nach Punkten splitten, die Strings in Zahlen parsen und die Zahlen für die vergleiche benutzen)
- Du rufst mit der Liste und einer Instanz Deines Comparators Collections.sort auf 
  (http://download.oracle.com/javase/6/docs/api/java/util/Collections.html)
 
Zuletzt bearbeitet von einem Moderator:
S

Smoothi

Gast
Hab nun meiner Entity-Klasse das Comperable-Interface übergeben. In der compareTo-Methode habe ich die IP-Adresse aufgesplittet und die einzelnen Blöcke auf Länge geprüft. Falls es 1 Zeichen ist, dann wird vorn eine 0 angefügt. Danach wird noch auf 2 Zeichen geprüft und ebenfalls ggf. eine 0 angefügt. Diese Blöcke werden dann wieder zusammengefügt und per compareTo() verglichen.

Funktioniert wunderbar. ;)
 
S

Smoothi

Gast
Validierer-Annotationen, Getter/Setter und die Entity-Standard-Methoden habe ich mal rausgelassen. ;)

Java:
@Entity
@Table (name="IPAdresse")
public class IPAddress implements Serializable, Comparable<IPAddress> {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column (name="ID", unique=true)  
    private Long id;
    
    @Column (name="IP") 
    private String ip;

    @Override
    public int compareTo(IPAddress otherIP) {
        if (otherIP.getSortIp() == null && this.getSortIp() == null) {
            return 0;
        }
        if (this.getSortIp() == null) {
            return 1;
        }
        if (otherIP.getSortIp() == null) {
            return -1;
        }
        return this.getSortIp().compareTo(otherIP.getSortIp());
    }
    
    /*
     * Teilt die IP in Blöcke auf
     * 
     * @return aufgefüllte IP-Adresse
     */
    public String getSortIp() {
        String ip4 = this.ip;
        String ip3 = ip4.substring(0, ip4.lastIndexOf("."));
        String ip2 = ip3.substring(0, ip3.lastIndexOf("."));
        String ip1 = ip2.substring(0, ip2.lastIndexOf("."));
        
        ip2 = ip2.substring(ip2.lastIndexOf(".") + 1);
        ip3 = ip3.substring(ip3.lastIndexOf(".") + 1);
        ip4 = ip4.substring(ip4.lastIndexOf(".") + 1);
        
        return fillIp(ip1) + "." + fillIp(ip2) + "." + fillIp(ip3) + "." + fillIp(ip4);
    }
    
    /*
     * Füllt einen Block einer IP mit Nullen auf
     * 
     * @param ip IP-Block
     * @return aufgefüllter IP-Block
     */
    public String fillIp(String ip) {
        if (ip.length() == 1) {
            ip = "0" + ip;
        }
        if (ip.length() == 2) {
            ip = "0" + ip;
        }
        
        return ip;
    }
}
 
N

nillehammer

Gast
Gut, dass es geht, aber doch eine Menge Code für das gewünschte Ergebnis. Ich glaube, mit dem Parsen der einzelnen Stellen der IP nach int und dem CompareToBuilder von apache commons-lang wirst Du auf Dauer glücklicher. Der Code sieht dan ungefähr so aus (aus dem Gedächtnis direkt in den Editor getippt, also bitte nicht böse über Codefehler sein):
[Java]
public final int compareTo(final IPAddress that) {

final CompareToBuilder builder = new CompareToBuilder();
final int[] thisIpArr = ipStrToIntArr(this.ip);
final int[] thatIpArr = ipStrToIntArr(that.ip);

for (int i = 0; i < thisIpArr.length; i++) {
builder.append(this.ipArr, thatIpArr);
}

return builder.toComparison();
}

private static int[] ipStrToIntArr(final String ipStr) {

final String[] ipStrArr = ipStr.split("\\.");
final int[] ipIntArr = new int[ipStrArr.length];

for (int i = 0; i< ipStrArr.length; i++ ) {
ipIntArr = Integer.parseInt(ipStrArr);
}

return ipIntArr;
}
[/Java]
 
Zuletzt bearbeitet von einem Moderator:

Ähnliche Java Themen


Oben