Dynamiczne zapytania JDBC + SQL?

0

Mam pytanie jak stworzyć dynamiczne zapytanie do bazy?
Powiedzmy ze mam coś takiego co niestety też nie działa...

	       
 pstmt = con.prepareStatement( "SELECT * FROM BAZA_X WHERE COL_1 = ?," +
	        		"Col_2= ?, Col_3 = ?, col_4 = ?,"+
	        		"Col_5 = ? Col_6 = ?");
	        pstmt.setString(1, x1);
	        pstmt.setString(2, x2);
	        pstmt.setString(3, x3);
	        pstmt.setInt(5, x4);
	        pstmt.setString(4, x5);
	        pstmt.setString(6, x6);
	        pstmt.executeUpdate();
	        pstmt.close()

Parametry są przekazywanie do funkcji, konwertowane odpowiednio na string/int/etc i podstawiane do pstmt.setXXX() jesli nie ma jakiegoś parametru to porostu pomija go w zapytaniu. Tak ma to wyglądać, niestety ten kod nie działa.
w Hibernate to dość proste sprawdzam if'em czy przekazany parametr ma jakaś wartość i robię wpis

if(par_1.isEmpty()==False) con.add(Restrictions.ilike("Col_2",Par_1));

i tak razy n parametrów później tylko sumuje, wsadzam do listy<typ> i wysyłam do modelu tabeli a jak by to wyglądało w JDBC? Bo przeglądam tutki i dokumentacje ale tam wszędzie jest tylko statyczne zapytanie?
W pstmt nie da się wstawiać np

 if(par_1.isEmpty()==false)to string par_1 = " Col_1 = " +par_1 

Wie ktoś jak to rozwiązać?
Może rozwiązanie jest dość banalne a ja jestem już zmęczony i nawet o tym nie pomyślałem...

0

Możesz pobawić się z http://openhms.sourceforge.net/sqlbuilder/ , ale to duża armata. Względnie napisać własny builder. W samym API JDBC nie ma obsługi dynamicznych zapytań.

0

Nie ma możliwości zrobienia koniunkcji zapytania?
Analogicznie do criteria w Hibernate?
jeśli jakiś warunek nie został podany to nie uwzględniaj go w zapytaniu?
A jak sobie radzono przed EJB i Hibernatebe z takimi zapytaniami tylko na tych parametrach które podał użytkownik?

0

Żeby to zrobić musiałbyś tworzyć zapytanie za pomocą jakiegoś buildera, a nie jako string.

0

WILSON GODDAMN IT! ;]
A nie da się tego jakoś obejść bez buildera?

0

No nie. Zresztą w Hibernate/JPA też korzystasz z buildera. Jeżeli nie chcesz się bawić to ściągnij to co dałem w pierwszym poście. Ułatwia życie.

0

udało mi się rozwiązać problem bez buildera

0

Jak udało Ci się rozwiązać problem to podziel się z nami jak to zrobiłeś?

0

Jasne w sumie mogłem od raz wkleić kod, od razu mówię że jest to rozwiązanie nie estetyczne i wielkość if;a rośnie proporcjonalnie do ilości kolumn ;]
A to KOD:

				
String sql="SELECT * FROM hibernatedata WHERE ";

			if(Id.isEmpty()==false){
				sql += "EmpID = "+"'"+Id+"'";
			}
			if(Fname.isEmpty()==false){
				if(Id.isEmpty()==false){
					sql += " AND ";
				}
				sql += "EmpFirstName = "+"'"+Fname+"'";
			}
			if(Lname.isEmpty()==false){
				if(Fname.isEmpty()==false || Id.isEmpty()==false){
					sql += " AND ";
				}
				sql += "EmpLastName = "+"'"+Lname+"'";
			}

			if(Tel.isEmpty()==false){
				if(Lname.isEmpty()==false || Fname.isEmpty()==false || Id.isEmpty()==false){
					sql += " AND ";
				}
				sql += "EmpTel = "+"'"+Tel+"'";
			}

			if(Worker.isEmpty()==false){
				if(Tel.isEmpty()==false || Lname.isEmpty()==false || Fname.isEmpty()==false || Id.isEmpty()==false){
					sql += " AND ";
				}
				sql += "EmpWorker = "+"'"+Worker+"'";
			}
			if(Age.isEmpty()==false){
				if(Worker.isEmpty()==false || Tel.isEmpty()==false || Lname.isEmpty()==false || Fname.isEmpty()==false || Id.isEmpty()==false){
					sql += " AND ";
				}
				sql += "EmpWorker = "+"'"+Age+"'";
			}
			if(Dep.isEmpty()==false){
				if(Worker.isEmpty()==false || Age.isEmpty()==false || Tel.isEmpty()==false || Lname.isEmpty()==false || Fname.isEmpty()==false || Id.isEmpty()==false){
					sql += " AND ";
				}
				sql += "EmpDep = "+"'"+Dep+"'";
			} 
System.out.println(sql);

i w zależności od tego co podamy na wejście mogą to być dowolne parametry z danych kolumn w dowolnej mieszance to ify budują odpowiedniego string
Na zdrowie! ;p

0

Czy słyszałeś o SQL Injection?
https://www.owasp.org/index.php/Preventing_SQL_Injection_in_Java
W tym przypadku SQL Injection raczej nie będzie groźny, ale lepiej zrobić sobie dobry nawyk.

Przy okazji - zamiast pisać "Id.isEmpty() == false" lepiej dać "!Id.isEmpty()". Kolejna rzecz to zmienne zaczynające się od wielkiej litery.

Jeszcze mała wskazówka:
Na początku klauzuli WHERE daj "1=1", tzn.

SELECT * FROM hibernatedata WHERE 1=1

dzięki temu nie będą potrzebne te wszystkie ify przy wstawianiu AND. Będziesz mógł od razu napisać:

sql += " AND EmpID = :id";

No i na koniec - użyj klasy StringBuilder, a nie zwykłego sklejania napisów.

1 użytkowników online, w tym zalogowanych: 0, gości: 1