javax.persistence.Query
Query query = ....
query.setParameter("PARAM_1","1")
.setParameter("PARAM_2","2")
.setParameter("PARAM_3","3")
...
...;
I want to get parameters and write Console. Like this;
System out ;
PARAM_1 - 1
PARAM_2 - 2
PARAM_3 - 3
...
...
java.util.Set<Parameter<?>> params = query.getParameters();
for (Parameter p : params) {
String paramName = p.getName();
System.out.print(paramName + " - ");
System.out.println(query.getParameterValue(paramName));
}
You just had to look at the javadoc, the method getParameters()
Query q = ...;
...
Set<Parameter<?>> parameters = q.getParameters();
for (Parameter<?> param : parameters){
if (null == param.getName()){
System.out.print(param.getPosition());
} else {
System.out.print(param.getName());
}
System.out.println(" - ");
System.out.println(q.getParameterValue(param));
}
You can try this:
Query query = ...;
String[] keys = new String[] {"PARAM_1", "PARAM_2", "PARAM_3"};
for(String key : keys) {
System.out.println(key + " - " + query.getParamValue(key));
}
check query interface. It has many methods like getParameter*(). See which one suits you.
getParameter() helps you to understand more. Please click here for more information.
This worked for me:
((NativeQueryImpl) fQuery).getNamedParameterMap()
Related
I have the following SQL string defined as a StringBuilder and want to replace all the ? with their appropriate keys:
SELECT a.accountNumber, a.eventKey, a.createdAtUtc FROM myFirstTable a, mySecondTable b where a.eventKey = b.eventKey and a.status = ? and
a.accountNumber = ?
I was hoping to use the following replace() function to retrieve the corresponding values from a map that are stored without the prefix "a." or ".b" but having trouble getting it working:
private String replace(StringBuilder sqlBuilder, Map<String, String> filterMap) {
for (Map.Entry<String, String> entry : filterMap.entrySet()) {
int startPositionOfKey = sqlBuilder.indexOf(entry.getKey());
int startIndex = startPositionOfKey + entry.getKey().length() + 4;
sqlBuilder.replace(startIndex, 1, "'" + entry.getValue() + "'");
}
return sqlBuilder.toString();
}
I'm using Dynamicloud and something is wrong in my code:
This is my code:
RecordModel contactFormModel = new RecordModel(contactModelId);
RecordModel userFormModel = new RecordModel(userContactModelId);
DynamicProvider<ContactForm> provider = new DynamicProviderImpl<ContactForm>(new RecordCredential(csk, aci));
contactFormModel.setBoundClass(ContactForm.class);
Query<ContactForm> query = provider.createQuery(contactFormModel);
query.setAlias("contact");
query.setProjection("contact.namef, contact.comments");
JoinClause join = Conditions.innerJoin(userFormModel, "user", "contact.id = user.contactid");
query.join(join);
try {
RecordResults<ContactForm> list = query.add(Conditions.like("contact.namef", "ProBusiness%")).list();
System.out.println("list = " + list.getFastReturnedSize());
if (list.getFastReturnedSize() > 0) {
System.out.println("Contact Name = " + list.getRecords().get(0).getName());
System.out.println("Contact Comments = " + list.getRecords().get(0).getComments());
}
} catch (DynamicloudProviderException e) {
e.printStackTrace();
}
This code throws the following Exception:
org.dynamicloud.exception.DynamicloudProviderException: Invalid statement. Please check aliases, field identifiers, projections and query conditions.
What's wrong?
Thanks!
Hi
The problems is the missing "id" in your projection section. You need to set the id of one model involved in your JoinClause.
Dynamicloud always order the results by Id, in this case the query has ambiguous columns user.id and contact.id"
Try to put the following id in your projection (of course depends of your needs):
query.setProjection("contact.id, contact.namef, contact.comments");
Hope this helps!
How can I print the value of my HashMap like this:
String hashMapValues = PHOTO_IDS.get(all values);
hashMapValues output as :
id1, id2, id3, id4, id5
HashMap<String,String> PHOTO_IDS;
onCreate....
PHOTO_IDS = new HashMap<String, String>();
if(vc.readLAST_TAKEN_PIC().equals("imageCam1")) { PHOTO_IDS.put("imageCam1", id); }
else if(vc.readLAST_TAKEN_PIC().equals("imageCam2")) { PHOTO_IDS.put("imageCam2", id); }
else if(vc.readLAST_TAKEN_PIC().equals("imageCam3")) { PHOTO_IDS.put("imageCam3", id); }
else if(vc.readLAST_TAKEN_PIC().equals("imageCam4")) { PHOTO_IDS.put("imageCam4", id); }
else if(vc.readLAST_TAKEN_PIC().equals("imageCam5")) { PHOTO_IDS.put("imageCam5", id); }
many many thanks for help.
UPDATED_____________________________________________
Thank you all for your reply. here is the working code:
String hashmapValues = PHOTO_IDS.values().toString();
TMP_PHOTO_ID = hashmapValues.replaceAll("[\\[\\]]", "");
You can use Map.getValues() for this purpose.
like
System.out.println(PHOTO_IDS .values());
Output will be like
[id1, id2, id3, id4, id5]
Here you need to relace [ and ] characters from string.
You can use entrySet() to print all values like this:
UPDATE : Using StringBuilder
StringBuilder s = new StringBuilder();
for(Entry<String,String> e : PHOTO_IDS.entrySet()){
s.append(e.getValue() + ", ");
}
String result = s.toString();
Refer HashMap#entrySet() java documentation for more information.
There is one more way to get the comma-seperated values directly as below :
String result = PHOTO_IDS.values().toString();
But this will return output as [id1, id2, id3, id4, id5], so you just need to get rid of those brackets[] which you can do easily by using substring
If you don't want the brackets around your value list, you can do the following. But for all solutions if you are concerned about order, you may want to consider using a LinkedHashMap
StringBuilder sb = new StringBuilder();
for(String val : map.values()){
sb.append(val+",");
}
String result = sb.toString();
System.out.println(result.substring(0, result.length() - 1)); //This will remove the last comma.
I have requirement in Java to fire a query on MS SQL like
select * from customer
where customer.name in ('abc', 'xyz', ...,'pqr');
But I have this IN clause values in the form of ArrayList of String. For ex: the list look like {"abc","xyz",...,"pqr"}
I created a Prepared Statement :
PreparedStatement pStmt = conn.prepareStatement(select * from customer
where customer.name in (?));
String list= StringUtils.join(namesList, ",");
pStmt.setString(1,list);
rs = pStmt.executeQuery();
But the list is like "abc,xyz,..,pqr", but I want it as "'abc','xyz',..,'pqr'"
so that I can pass it to Prepares Statement.
How to do it in JAva with out GUAVA helper libraries.
Thanks in Advance!!
I know this is a really old post but just in case someone is looking for how you could do this in a Java 8 way:
private String join(List<String> namesList) {
return String.join(",", namesList
.stream()
.map(name -> ("'" + name + "'"))
.collect(Collectors.toList()));
}
List<String> nameList = ...
String result = nameList.stream().collect(Collectors.joining("','", "'", "'"));
For converting the string you can try this:
String list= StringUtils.join(namesList, "','");
list = "'" + list + "'";
But i dont thing it's a good idea to pass one string for multiple params.
Even if you formatted the String as you wish, it won't work. You can't replace one placeholder in the PreparedStatement with multiple values.
You should build the PreparedStatement dynamically to have as many placeholders as there are elements in your input list.
I'd do something like this :
StringBuilder scmd = new StringBuilder ();
scmd.append ("select * from customer where customer.name in ( ");
for (int i = 0; i < namesList.size(); i++) {
if (i > 0)
scmd.append (',');
scmd.append ('?');
}
scmd.append (")");
PreparedStatement stmt = connection.prepareStatement(scmd.toString());
if (namesList.size() > 0) {
for (int i = 0; i < namesList.size(); i++) {
stmt.setString (i + 1, namesList.get(i));
}
}
rs = stmt.executeQuery();
You can use a simple separator for this type of activity. Essentially you want an object that evaluates to "" the first time around but changes after the first request to return a defined string.
public class SimpleSeparator<T> {
private final String sepString;
boolean first = true;
public SimpleSeparator(final String sep) {
this.sepString = sep;
}
public String sep() {
// Return empty string first and then the separator on every subsequent invocation.
if (first) {
first = false;
return "";
}
return sepString;
}
public static void main(String[] args) {
SimpleSeparator sep = new SimpleSeparator("','");
System.out.print("[");
for ( int i = 0; i < 10; i++ ) {
System.out.print(sep.sep()+i);
}
System.out.print("]");
}
}
I did it as following with stream. Almost the same, but a bit shorter.
nameList = List.of("aaa", "bbb", "ccc")
.stream()
.map(name -> "'" + name + "'")
.collect(Collectors.joining(","));
I guess the simplest way to do it is using expression language like that:
String[] strings = {"a", "b", "c"};
String result = ("" + Arrays.asList(strings)).replaceAll("(^.|.$)", "\'").replace(", ", "\',\'" );
I'm using Tapestry5 and Hibernate. I'm trying to build a criteria query that uses dynamic restrictions generated from the URL. My URL context is designed like a key/value pair.
Example
www.mywebsite.com/make/ford/model/focus/year/2009
I decode the parameters as followed
private Map<String, String> queryParameters;
private List<Vehicle> vehicles;
void onActivate(EventContext context) {
//Count is 6 - make/ford/model/focus/year/2009
int count = context.getCount();
if (count > 0) {
int i;
for (i = 0; (i + 1) < count; i += 2) {
String name = context.get(String.class, i);
String value = context.get(String.class, i + 1);
example "make"
System.out.println("name " + name);
example "ford"
System.out.println("value " + value);
this.queryParameters.put(name, value);
}
}
this.vehicles = this.session.createCriteria(Vehicle.class)
...add dynamic restrictions.
}
I was hoping someone could help me to figure out how to dynamically add the list of restrictions to my query. I'm sure this has been done, so if anybody knows of a post, that would be helpful too. Thanks
Exactly as the other answer said, but here more spelt out. I think the crux of your question is really 'show me how to add a restriction'. That is my interpretation anyhow.
You need to decode each restriction into its own field.
You need to know the Java entity property name for each field.
Then build a Map of these 2 things, the key is the known static Java entity property name and the value is the URL decoded data (possibly with type conversion).
private Map<String, Object> queryParameters;
private List<Vehicle> vehicles;
void onActivate(EventContext context) {
//Count is 6 - make/ford/model/focus/year/2009
int count = context.getCount();
queryParameters = new HashMap<String,Object>();
if (count > 0) {
int i;
for (i = 0; (i + 1) < count; i += 2) {
String name = context.get(String.class, i);
String value = context.get(String.class, i + 1);
Object sqlValue = value;
if("foobar".equals(name)) {
// sometime you don't want a String type for SQL compasition
// so convert it
sqlValue = UtilityClass.doTypeConversionForFoobar(value);
} else if("search".equals(name) ||
"model".equals(name) ||
"year".equals(name)) {
// no-op this is valid 'name'
} else if("make".equals(name)) {
// this is a suggestion depends on your project conf
name = "vehicleMake.name";
} else {
continue; // ignore values we did not expect
}
// FIXME: You should validate all 'name' values
// to be valid and/or convert to Java property names here
System.out.println("name " + name);
System.out.println("value " + value);
this.queryParameters.put(name, sqlValue);
}
}
Criteria crit = this.session.createCriteria(Vehicle.class)
for(Map.Entry<String,Object> e : this.queryParameters.entrySet()) {
String n = e.getKey();
Object v = e.getValue();
// Sometimes you don't want a direct compare 'Restructions.eq()'
if("search".equals(n))
crit.add(Restrictions.like(n, "%" + v + "%"));
else // Most of the time you do
crit.add(Restrictions.eq(n, v));
}
this.vehicles = crit.list(); // run query
}
See also https://docs.jboss.org/hibernate/orm/3.5/reference/en/html/querycriteria.html
With the above there should be no risk of SQL injection, since the "name" and "n" part should be 100% validated against a known good list. The "value" and "v" is correctly escaped, just like using SQL position placeholder '?'.
E&OE
I would assume you would just loop over the parameters Map and add a Restriction for each pair.
Be aware that this will open you up to sql injection attacks if you are not careful. the easiest way to protect against this would be to check the keys against the known Vehicle properties before adding to the Criteria.
Another option would be to create an example query by building an object from the name/value pairs:
Vehicle vehicle = new Vehicle();
int count = context.getCount();
int i;
for (i = 0; (i + 1) < count; i += 2) {
String name = context.get(String.class, i);
String value = context.get(String.class, i + 1);
// This will call the setter for the name, passing the value
// So if name is 'make' and value is 'ford', it will call vehicle.setMake('ford')
BeantUtils.setProperty(vehicle, name, value);
}
// This is using a Hibernate example query:
vehicles = session.createCriteria(Vehicle.class).add(Example.create(vehicle)).list();
See BeanUtils.setProperty and Example Queries for more info.
That assumes you are allowing only one value per property and that the query parameters map to the property names correctly. There may also be conversion issues to think about but I think setProperty handles the common ones.
If they are query paramaters you should treat them as query parameters instead of path parameters. Your URL should look something like:
www.mywebsite.com/vehicles?make=ford&model=focus&year=2009
and your code should look something like this:
public class Vehicles {
#ActivationRequestParameter
private String make;
#ActivationRequestParameter
private String model;
#ActivationRequestParameter
private String year;
#Inject
private Session session;
#OnEvent(EventConstants.ACTIVATE)
void activate() {
Criteria criteria = session.createCriteria(Vehicle.class);
if (make != null) criteria.add(Restrictions.eq("make", make));
if (model != null) criteria.add(Restrictions.eq("model", model));
if (year != null) criteria.add(Restrictions.eq("year", year));
vehicles = criteria.list();
}
}
Assuming you are using the Grid component to display the vehicles I'd highly recommend using the HibernateGridDataSource instead of making the query in the "activate" event handler.
public class Vehicles {
#ActivationRequestParameter
private String make;
#ActivationRequestParameter
private String model;
#ActivationRequestParameter
private String year;
#Inject
private Session session;
#OnEvent(EventConstants.ACTIVATE)
void activate() {
}
public GridDataSource getVehicles() {
return new HibernateGridDataSource(session, Vehicles.class) {
#Override
protected void applyAdditionalConstraints(Criteria criteria) {
if (make != null) criteria.add(Restrictions.eq("make", make));
if (model != null) criteria.add(Restrictions.eq("model", model));
if (year != null) criteria.add(Restrictions.eq("year", year));
}
};
}
}