0

ユーザーが jpa/Criteria を使用してデータベースから 1 人または複数のユーザーを動的に選択できるようにするソフトウェアを開発しています。

編集/更新: -AND を使用して成長する述語を使用するようになりました。問題は、正しいフィールドを示しているのではなく、ユーザーが入力したものを Java が探している文字列だけを示していることです。-私がアドバイスされたように、パスをどのように操作できるかをまだ確認する必要があります。

ユーザーが d を PC_Name として、d を Name として、c を Vorname として入力すると、詳細な eclipselink に次のように表示されます。

[EL Fine]: sql: 2012-07-25 15:44:13.173--ServerSession(24105143)--Connection(13480046)--Thread(Thread[main,5,main])--SELECT PERSONALNUMMER, GEBURTSTAG, GRUPPE, IP, MOBIL, NAME, PC_NAME, TELEFON, VORNAME FROM MITARBEITERTABELLE WHERE ((? LIKE ? AND ? LIKE ?) AND ? LIKE ?)
    bind => [PC_Name, %d%, Name, %b%, Vorname, %c%]

これは、私が言っていることを確認します.nを名前として入力すると、nは常に名前に属しているため、データベース全体を取得します..

編集/更新の終了

動作するSQLバージョンは次のとおりです。

try{
    String selectString ="SELECT  * FROM mitarbeitertabelle WHERE ";
    selectString=StringModulierung(selectString);

    PreparedStatement selectMitarbeiter = con.prepareStatement(selectString);
    int i =1;
    if(isNameSuche()){selectMitarbeiter.setString (i,this.wc+_Name+this.wc); i++;}
    if(isVornameSuche()){ selectMitarbeiter.setString (i, this.wc+_Vorname+this.wc); i++;}
    if(isPersonalnummerSuche()){selectMitarbeiter.setString (i, this.wc+_Personalnummer+this.wc); i++;}
    if(isPC_NameSuche()){selectMitarbeiter.setString (i, this.wc+_PC_Name+this.wc); i++;}
    if(isIPSuche()){selectMitarbeiter.setString (i, this.wc+_IP+this.wc); i++;}
    if(isTelefonSuche()){ selectMitarbeiter.setString (i, this.wc+_Telefon+this.wc); i++;}
    if(isGeburtstagSuche()){selectMitarbeiter.setString (i, this.wc+_Geburtstag+this.wc); i++;}
    if(isGruppeSuche()){ selectMitarbeiter.setString (i, this.wc+_Gruppe+this.wc); i++;}
    if(isMobilSuche()){ selectMitarbeiter.setString (i, this.wc+_Mobil+this.wc); i++;}

    System.out.println(selectMitarbeiter.toString());
    ResultSet ergebnis=selectMitarbeiter.executeQuery();`

と:

public String StringModulierung(String str){
boolean erster=true;

    if(isNameSuche()){ str=str.concat("Name LIKE ? ");
        erster=false;
    }
    if(isVornameSuche()){ if(erster){str=str.concat("Vorname LIKE ? ");erster=false;
    }else{str=str.concat("AND Vorname LIKE ? ");}
}
    if(isPersonalnummerSuche()){ if(erster){str=str.concat("Personalnummer LIKE ? ");erster=false;
    }else{str=str.concat("AND Personalnummer LIKE ? ");}
}
    if(isPC_NameSuche()){ if(erster){str=str.concat("PC_Name LIKE ? ");erster=false;
    }else{str=str.concat("AND PC_Name LIKE ? ");}
}
    if(isIPSuche()){ if(erster){str=str.concat("IP LIKE ? ");erster=false;
                        }else{str=str.concat("AND IP LIKE ? ");}
    }
    if(isTelefonSuche()){ if(erster){str=str.concat("Telefon LIKE ? ");erster=false;
    }else{str=str.concat("AND Telefon LIKE ? ");}
}
    if(isGeburtstagSuche()){ if(erster){str=str.concat("Geburtstag LIKE ? ");erster=false;
                            }else{str=str.concat("AND Geburtstag LIKE ? ");}
}
    if(isGruppeSuche()){ if(erster){str=str.concat("Gruppe LIKE ? ");erster=false;
                        }else{str=str.concat("AND Gruppe LIKE ? ");}
}
    if(isMobilSuche()){ if(erster){str=str.concat("Mobil LIKE ? ");erster=false;
    }else{str=str.concat("AND Mobil LIKE ? ");}
}

    return str;
}

これが私がjpaで行ったことです:

CriteriaBuilder cb = EM.getCriteriaBuilder();
        CriteriaQuery<Mitarbeiter2> q = cb.createQuery(Mitarbeiter2.class);
        Root<Mitarbeiter2> mit= q.from(Mitarbeiter2.class);



        ParameterExpression<String> pc_name = cb.parameter(String.class,"PC_Name_p");
        ParameterExpression<String> ip = cb.parameter(String.class,"IP_p");
        ParameterExpression<String> pers_num = cb.parameter(String.class,"Personalnummer_p");
        ParameterExpression<String> name = cb.parameter(String.class,"Name_p");
        ParameterExpression<String> vorname = cb.parameter(String.class,"Vorname_p");
        ParameterExpression<String> telefon = cb.parameter(String.class,"Telefon_p");
        ParameterExpression<String> geburtstag = cb.parameter(String.class,"Geburtstag_p");
        ParameterExpression<String> gruppe = cb.parameter(String.class,"Gruppe_p");
        ParameterExpression<String> mobil = cb.parameter(String.class,"Mobil_p");


        Predicate p = cb.conjunction();

        if(isPC_NameSuche()){
            p = cb.and(p, cb.like(pc_name, this.getWc()+_PC_Name+this.getWc() ));

}
        if(isIPSuche()) {
            p = cb.and(p, cb.like(ip,this.getWc()+_IP+this.getWc()));
            }
        if(isPersonalnummerSuche()) {
            p = cb.and(p, cb.like(pers_num, this.getWc()+_Personalnummer+this.getWc() ));}

        if(isNameSuche()){
            p = cb.and(p, cb.like(name, this.getWc()+_Name+this.getWc()));
            }
        if(isVornameSuche()) {
            p = cb.and(p, cb.like(vorname, this.getWc()+_Vorname+this.getWc()));}
        if(isTelefonSuche()) {
            p = cb.and(p, cb.like(telefon, this.getWc()+_Telefon+this.getWc() ));}
        if(isGeburtstagSuche()){
            p = cb.and(p, cb.like(geburtstag, this.getWc()+_Geburtstag+this.getWc()));}
        if(isGruppeSuche()) {
            p = cb.and(p, cb.like(gruppe, this.getWc()+_Gruppe+this.getWc()));}
        if(isMobilSuche()) {
            p = cb.and(p, cb.like(mobil, this.getWc()+_Mobil+this.getWc()));}

        q.where(p);
        q.select(mit);
        TypedQuery<Mitarbeiter2> tq = EM.createQuery(q);

        tq.setParameter("PC_Name_p", "PC_Name"); // searches this.getWc()+_Mobil+this.getWc() in  PC_Name !
        tq.setParameter("IP_p", "IP");
        tq.setParameter("Personalnummer_p", "Personalnummer");
        tq.setParameter( name/**entered by user*/, "Name"/**should be the field */);
        tq.setParameter("Vorname_p", "Vorname");
        tq.setParameter("Telefon_p", "Telefon");
        tq.setParameter("Geburtstag_p","Geburtstag" );
        tq.setParameter("Gruppe_p", "Gruppe");
        tq.setParameter("Mobil_p" ,"Mobil");





        List<Mitarbeiter2> ergebnis= tq.getResultList();

次の2つのソリューションを組み込みました。

where 条件を動的に追加するには、各 Predicate が次のように定義されている List を使用できます。

> Predicate p = cb.like(...);

または、次のように単一の述語を動的に変更できます。

>  Predicate p = cb.conjunction(); for ( filter : filters) {
    >     p = cb.and(p, cb.like(...)); }

q.where を実行すると、WHERE 式が設定されます。

追加しません。つまり、最後に呼び出した q.where は、クエリに設定されたものです。

あなたがする必要があるのは、ブール式を作成することです(ANDが必要だと思います)。

次に、ユーザー q.where で式を設定します。

ご協力いただきありがとうございます ;) 。

ハラルド

4

3 に答える 3

1

私が抱えていた2つの問題は次のとおりです。1)Criteriaを使用してクエリを動的に構築する方法、(SQLで)this(多くの異なる述語を含む)のようなクエリを取得する方法は?

SELECT * FROM mitarbeitertabelle where (1) like (2) and (3) like (4)...

これは、実行時に、ユーザーが mitarbeiter (ドイツ語で従業員) を検索するために使用する 1 つまたは複数の条件を選択できることを意味します。

2) オブジェクトの属性へのリンクを設定する方法は?

1)これを行うには、基準が選択されている場合、新しい述語を追加するたびに変更される述語を使用して、述語を作成する必要があります。

p= criteriabuilder.and(p, criteriabuilder.like(path object linking to the right attribute, String s used for the search));

2) 正しいパスにより、正しい属性へのリンクが可能になります。上で使っています。ここで重要なことは、パスがないと、私が知っている限り、属性へのリンクを持つことができないということです ;) .

その後、述語をパラメーターとして受け取る where 句と、ルート (データベースで検索する場所) をパラメーターとして受け取る select 句を追加して、SQL コマンドを実行するだけです。

    q.where(p);
    q.select(mit);

次に、結果を取得します。

List<Mitarbeiter2> ergebnis= EM.createQuery(q).getResultList();

パラメータ式オブジェクトを使用していないため、パラメータ式オブジェクトを入力して使用する必要はありません。検索に使用される文字列は、実行時に like 句に直接設定されます。

コード全体(私の変数、名前、..を含む)は次のとおりです。

            CriteriaBuilder cb = EM.getCriteriaBuilder();
        CriteriaQuery<Mitarbeiter2> q = cb.createQuery(Mitarbeiter2.class);
        Root<Mitarbeiter2> mit= q.from(Mitarbeiter2.class);

            Path<String> pc_name2 = mit.get("PC_Name");
        Path<String> ip2 = mit.get("IP");
        Path<String> pers_num2 = mit.get("Personalnummer");
        Path<String> name2 = mit.get("Name");
        Path<String> vorname2 = mit.get("Vorname");
        Path<String> telefon2 = mit.get("Telefon");
        Path<String> geburtstag2 = mit.get("Geburtstag");
        Path<String> gruppe2 = mit.get("Gruppe");
        Path<String> mobil2 = mit.get("Mobil");

            Predicate p = cb.conjunction();

        if(isPC_NameSuche()){
            p = cb.and(p, cb.like(pc_name2, this.getWc()+_PC_Name+this.getWc() ));

}
        if(isIPSuche()) {
            p = cb.and(p, cb.like(ip2,this.getWc()+_IP+this.getWc()));
            }
        if(isPersonalnummerSuche()) {
            p = cb.and(p, cb.like(pers_num2, this.getWc()+_Personalnummer+this.getWc() ));}

        if(isNameSuche()){
            p = cb.and(p, cb.like(name2, this.getWc()+_Name+this.getWc()));
            }
        if(isVornameSuche()) {
            p = cb.and(p, cb.like(vorname2, this.getWc()+_Vorname+this.getWc()));}
        if(isTelefonSuche()) {
            p = cb.and(p, cb.like(telefon2, this.getWc()+_Telefon+this.getWc() ));}
        if(isGeburtstagSuche()){
            p = cb.and(p, cb.like(geburtstag2, this.getWc()+_Geburtstag+this.getWc()));}
        if(isGruppeSuche()) {
            p = cb.and(p, cb.like(gruppe2, this.getWc()+_Gruppe+this.getWc()));}
        if(isMobilSuche()) {
            p = cb.and(p, cb.like(mobil2, this.getWc()+_Mobil+this.getWc()));}

        q.where(p);
        q.select(mit);
            List<Mitarbeiter2> ergebnis= EM.createQuery(q).getResultList();

@perissf と @aviram-segal のご協力に感謝します。私の回答で何かが理解しにくいと思われる場合は、遠慮なくコメントしてください。

于 2012-07-26T07:03:56.720 に答える
0

q.where を実行すると、WHERE 式が設定されます。

追加しません。つまり、最後に呼び出した q.where は、クエリに設定されたものです。

あなたがする必要があるのは、ブール式を作成することです(ANDが必要だと思います)。

次に、ユーザー q.where で式を設定します。

于 2012-07-25T10:23:38.997 に答える
0

あなたのequal句では、次の表現を使用しています。

ParameterExpression<String> pc_name = cb.parameter(String.class,"PC_Name");

代わりにこれを試してください:

Path<Mitarbeiter2> pc_name = mit.get("PC_Name");

または、メタモデルで生成されたクラスを使用して、

Path<Mitarbeiter2> pc_name = mit.get(Mitarbeiter2_.pc_name);

現在、式をテストすることはできませんPathが、次のように動作することを確信しています。

q.where(cb.like(mit.get("PC_Name"), pc_name));

また:

q.where(cb.like(mit.get(Mitarbeiter2_.pc_name), pc_name));

動的に条件を追加するには、次のように各述語を定義whereする場所を使用できます。List<Predicate>

Predicate p = cb.like(...);

Predicateまたは、次のように単一のものを動的に変更できます。

Predicate p = cb.conjunction();
for ( filter : filters) {
    p = cb.and(p, cb.like(...));
}

最後に、文字列を比較する場合は、比較を行う前にすべてを同じケースに変換することを忘れないでください。

于 2012-07-25T10:38:38.663 に答える