[JPA/JPQL] IP-Adressen ordnen.

  • Themenstarter Themenstarter Smoothi
  • Beginndatum Beginndatum
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
 
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.
 
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. 😉
 
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:
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. 😉
 
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;
    }
}
 
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:

Zurück
Oben