I'm pretty new to the whole SQL and Java thing, but here I'm actually really confused.
I have a method which is called by invoking a few array parameters, as following
Method(String[], int, int[], int[])
I'm doing a ResultSet to check to see if there are any rows available where there is an ID match for the searched item.
ResultSet group = statement.executeQuery("SELECT * FROM `circulation` WHERE `ItemID` = "+itemID);
However, I'm completely stumped here on how to construct the method.
The String[], and int[] parameters are what is stored in the database, while the standard int parameter is the itemID. I have no idea how to go about doing this to call the Method correctly.
Darn, I thought I was doing good, too.
Arguments are normally used to provide information to the method being called. To get information from the method being called, you normally use a return value.
Your method seems to search rows in a database table named circulation for a given item ID. The item ID should thus be an argument. The found rows should be a returned value. The signature of the method should thus be:
Circulation[] findByItemId(int itemId);
Or better, using collections instead of arrays:
List<Circulation> findByItemId(int itemId);
What is Circulation? It's a class that represents what a row of the circulation table contains. So if the table contains an ID, a name and an item ID, this class would look like
public class Circulation {
private int id;
private String name;
private int itemId;
// constructor, getters, and other useful methods omitted for brevity
}
Your findByItemId() method will thus create an empty list of Circulation, then iterate over the rows of the result set, construct a Circulation instance for each row, and add the instance to the list. And then it will return that list.
Finally, you're using concatenation to build a SQL query taking parameters. This is dangerous. You should use a prepared statement instead. Read the tutorial about them.
Take a look at Apache commons-dbutils. It is a simple wrapper around JDBC and lets you convert your resultsets into any standard datastructures
You can use function
rs.getArray()
with columnName or ColumnLabel.
But this function return objects array and you can cast it to Integer and String.
Related
I have a Java Object, Record . It represents a single record as a result of SQL execution. Can CQEngine index collection of Record ?
My class is of the form
public class Record {
private List<String> columnNames;
private List<Object> values;
... Other getters
}
I have looked through some examples, but I have no luck there.
I want to index only specific column(s) with its name and corresponding value. Can this be achived using cqengine or is there any other alternatives to achieve the same.
Thanks.
That seems to be a strange way to model data, but you can use CQEngine with that model if you wish.
(First off, CQEngine will have no use for your column names so you can remove that field.)
To do this, you will need to define a CQEngine virtual attribute for each of the indexes in your list of values.
Each attribute will need to be declared with the data type which will be stored in that column/index, and will need to be able to cast the object at that index in your list of values, to the appropriate data type (String, Double, Integer etc.).
So let's say your Record has a column called 'price', which is of type Double, and is stored at index 5 in the list of values. You could define an attribute which reads it as follows:
public static final Attribute<Record, Double> PRICE =
attribute("PRICE", record -> ((Double) record.values.get(5));
If this sounds complicated, it's because that way of modelling data makes things a bit complicated :) It's usually easier to work with a data model which leverages the Java type system (which your model does not). As such, you will need to keep track of the data types etc. of each field programmatically yourself.
CQEngine itself will work fine with that model though, because at the end of the day CQEngine attributes don't need to read fields, the attributes are just functions which are programmed to fetch values.
There's a bunch of stuff not covered above. For example can your values be null? (if so, you should use the nullable variety of attributes as discussed in the CQEngine docs. Or, might each of your Record objects have different sets of columns? (if so, you can create attributes on-the-fly when you encounter a new column, but you should probably cache the attributes you have created somewhere).
Hope that helps,
Niall (CQEngine author)
The Java Tutorials by Oracle include a page, Class Literals as Runtime-Type Tokens.
The code there shows how passing a Class object as an argument can be used with generics to define the type of an object being instantiated with newInstance(). Their example code goes on to mention in comments:
Use reflection and set all of item's fields from sql results.
Collection<EmpInfo> emps = sqlUtility.select(EmpInfo.class, "select * from emps");
...
public static <T> Collection<T> select(Class<T> c, String sqlStatement) {
Collection<T> result = new ArrayList<T>();
/* Run sql query using jdbc. */
for (/* Iterate over jdbc results. */ ) {
T item = c.newInstance();
/* Use reflection and set all of item's
* fields from sql results.
*/
result.add(item);
}
return result;
}
I am wondering what such code looks like to use reflection to populate an object’s fields with the results of a row from a ResultSet.
➠Does anyone care to post an example of such code?
My interest is to see an example of reflection in action, and see how one might match up the members/properties of an object with the fields of the database row. Whether this approach is optimal or recommended is not the issue, so need for references to JDBC frameworks needed here.
I saved a StackMobModel object to the server and its data appears on the stackmob site correctly. I am able to query for all of the fields except for booleans (ex: new StackMobQuery().fieldIsGreaterThanOrEqualTo("age",20) )
All of the query types seem to take a String for the field name and either a String or int for the value to compare against. How can I query for boolean fields?
It is possible to go through the returned list and manually compare the boolean field to the desired one and create a new filtered list but this defeats the purpose of having a specific query.
Edit: also, how do you query for longs?
Nevermind. What you have to do is add a StackMobQueryField via the field() method.
.field(new StackMobQueryField("date").isGreaterThanOrEqualTo(date))
This has more options than the built-in field comparisons.
Since the play documentation on models is terrible I'll ask here. I have the basic code;
public static void Controller() {
List<Item> item = Item.find("SELECT itemname,id FROM Item WHERE itembool = true ORDER BY itemcreated ASC LIMIT 0,1").fetch();
if ( item == null ) {
notFound();
}
}
What I'm trying to do is get the value for 'itemname' returned for the first value returned from an SQL query (The real query is much more complicated and other things so it can't be replaced with methods). I can get the entire first object with item.get(0) but I can't figure out how to get the value of 'itemname' as a string and it doesn't seem to be documented anywhere.
Edit
Probably should have mentioned in the original question, I need to retrieve by field name, not index. I.E. I can't do items.get(0)[0]; I need to do items.get(0)['itemname'];
The documentation explains this if you read it, in here. Hibernate doesn't use SQL, but JPQL, which has a different syntax as it works with objects, not individual fields.
What you want to do can be achieved in two ways (both in the documentation):
List<Item> item = Item.find("SELECT i FROM Item i WHERE i.itembool = true ORDER BY i.itemcreated ASC").fetch(1);
List<Item> item = Item.find("itembool = true ORDER BY itemcreated ASC").fetch(1);
EDIT:
On the retrieval part, you will get a list of Item, so you can just access the field directly on the object:
item.get(0).getItemName();
Since Play uses Hibernate under the hood, you need to take a look at Hibernate's documentation.
In particular, SELECT itemname,id ... yields Object[] rather than Item, so that you can get itemname as follows:
List<Object[]> items = ...;
String itemname = items.get(0)[0];
well if you have to do a select itemname,id ..., you would not be able to do a items.get(0)["itemname"] because as axtavt and Pere have mentioned, you would get a Object[] back. You can instead create another (perhaps immutable) entity class that can be used in this query. Please refer to hibernate documentation for details. You can then model the entity based on your query requirements and use it to fetch information, thus letting hibernate handle all the magic number game for you. That ways, you would have a bean with filled up values that you can use to map back to your model class if you like.
HTH!
I have a question that I dont really know where to start. So I thought i'd ask it here.
Basically, I have a drop down with names in it. I want these names to be in alphabetical order.
Populating the drop down happens as follows;
I query a database and pull down an Id and Name, make a object called "UserList", and set the name and id variables with what I get back.
I then add this object to an ArrayList. I do this over and over.
I then convert this collection to an array, and pass it to my JSP page using
session.setAttribute("userList", UserList);
I then populate the drop down as below.
<c:forEach items="${userList}" var="c" >
`<html-el:option value="${c.id}"><c:out value="${c.name}"/></html-el:option> </c:forEach>
There probably is a simple answer but how to I sort these names?
You usually do it by invoking public static Collections.sort(List<T> list) with your ArrayList as the parameter, but take care to implement the Comparable interface or it won't work (if they are Strings then it's already implemented):
Collections.sort(yourList);
Otherwise if you have a custom class but you want to sort just over some string field inside you can delegate the compareTo method:
public class User implements Comparable<User> {
public int compareTo(User other) {
return userName.compareTo(other.userName);
}
}
Finally if noone is your case just roll your own compareTo method, it should return -1, 0 or 1 if the the calling object is less, equal to or greater than the passed one.
Michael, you should be using a join and an order by to get this data from the database, not retrieving and sorting in Java:
select person.id, person.name from person inner join person_company using(personid)
order by person.name;
And not trying to sort and do this in java (the syntax above may not be perfect, my MySQL's a bit rusty).
I think the most ideal solution to this problem is to sort them at the database query level. If the table is well indexed, this will be the fastest and arguable the "best" practice.
That being said, if you just want to sort that list and not start mucking on the database side, use Collections.sort and have your UserList implement Comparable<UserList>
Be careful to use the case insensitive string comparison, or your users will likely not appreciate the sorting results.
I would change the database query to return the rows in the order you want them.
If you are using SQL the query could look like the following.
SELECT Id, Name FROM Person ORDER BY Name;
This has some advantages over doing it in code.
It is faster.
You do not have to change your code.
It is less work.
You can try and override the compareTo method for UserList so that it compares the elements in an alphabetical way according to some string value. Then, call the sort method of the array list and it should sort them using the compareTo you overrode.
You could sort in the database, instead of firing many queries with
select Id, Name from Person where id = '+variable+';
You can loop over the variables and make a comma separated list , this way you only fire a single query
int[] variableList = wherever_you_get_it_from;
StringBuffer csv = new StringBuffer();
for (int i = 0; i < variableList.length; i++) {
csv.append(variableList[i]);
if (i < variableList.length - 1)
csv.append(",");
}
then give
select Id, Name from Person where id in ( +csv.toString()+) order by Name;
Since you are getting the user ids from a company table, you can join and fetch
select u.usrid, u.name from company c left join user u on c.usrid = u.usrid
where c.companyid in (comapnyid1, companyid2, companyid3) order by u.name;
You should use Collections.sort and either of
Make your User class implement Comparable interface
Create a UserListComparator implementing Comparator<UserList> interface
See Comparable interface documentation for details.