I have a query in Data Access Object DAOComments that joins users table and comments table and then store the result into Data Transfer Object DTOComments:
private static final String SQL_FIND_WITH_USERNAME =
"SELECT u.username, comments.* FROM users u JOIN comments
ON u.id = comments.id ORDER BY created_date DESC LIMIT 10;";
However, DTOComments does not have property "username" since it is the property of DTOUsers.
Option 1
So I decided to use Map<String, DTOComments>
In this case the map has username as KEY, DTOComments as VALUE.
But this approach will fails, because I care about the ORDER of result and that's why my query returns result in descending order. If I iterate the map on JSP page, the order is not consistent, so my JSP page would output the comment in random order.
(Even if order doesn't matter, I don't know if JSTL can display map's KEY. I know displaying the VALUE though)
Option 2
I could put the query result into ArrayList<DTOComments>
But I don't see any room to store the "username" now. Maybe I can add new property to DTOComments like private String username;
hmm... this would violate the concept of having DTO since it SHOULD reflect the database table schema.
Option 3
Create new class that hold all the information I need (ie. username + properties of DTOComments).
But just because I need one more property "username" in addition to the properties of DTOComments, creating new class seems not right way.
Could anyone give me advice how can I store all info returned by the query above in more organized way?
If I iterate the map on JSP page, the order is not consistent, so my JSP page would output the comment in random order.
That's the nature of HashMap. If you want to maintain insertion order in a Map, then you should be using LinkedHashMap instead. But the Map<User, Comment> approach has another disadvantage, if an user has posted more than one comment, you would be overwriting the previously inserted comment this way. You would like to use a Map<Comment, User> instead.
But IMHO it's better to make the User a property in Comment class, indicating a many-to-one relationship:
public class Comment {
private User user; // +getter +setter
}
This way you can end up with a List<Comment>.
That said, I wanted to comment on another statement of you:
I don't know if JSTL can display map's KEY. I know displaying the VALUE though)
You can iterate over a map using <c:forEach>. It goes over Map#entrySet(). Each iteration gives a Map.Entry object back which in turn has getKey() and getValue() methods.
Here's a kickoff example:
<c:forEach items="${map}" var="entry">
Key: ${entry.key}, value: ${entry.value}<br>
</c:forEach>
Related
I am trying to implement a many to one relationship. I plan to store an array of keys (datastore entity key) of one model in the other model's entity as List<String>.
e.g. Say 4 entities of Model A (a1,a2,a3,a4) have datastore keys : key1, key2, key3 and key4 respectively. Now I store an entity of Model B which has a property called "ids" as List<String>. "ids" has these String as the elements: key1, key2, key3 and key4.
Its all fine till now.
But how do I query the model B for each of these ids now?
What I want to do is something like this:
query.setFilter(FilterOperator.EQUAL.of(ids,"key1")).
Clearly this can not be done right now.
Now what I am doing is fetching the ids property of each B entity and then manually deserializing into a list of string and then checking if the key is present or not.
As you can see this is highly inefficient. How should I approach here? Should I store these mapping in a separate Model. I don't want to handle Joins, but I will have to if I can't get anything else than the present solution.
I am not using JPA or JDO and I plan not to use them.
Any help would be appreciated.
The query with EQUAL filter works fine for lists of values. Make sure you pass correct value when executing this query.
For example, you can store List, if you only use this entity on the server side.
If you need this list on the client side, and you always store keys for entities of the same kind, you can store a list of ids (List) or 'names` (List) used to create these keys. This will take much less space.
Since data stored in Mysql always has a column name, I thought it will be great if there is a way to retrieve the records in a key-value map.
The Hibernate mechanism for join queries can't help too much, as we could only retrieve the Object[] result and deserialize the result ourself, or we could use this:
This is most useful when used together with select new map:
select new map( max(bodyWeight) as max, min(bodyWeight) as min, count(*) as n )
from Cat cat
The query above gives a way of retrieving a map, but we have to define the key of the map(with as), I think it's just a case-by-case solution, it is not very elegant to hard-code the field name.
Isn't it better and generic that we find a way to automatically define the key of the retrieved map with just the column name? So can we send a map with all the fields and let the application choose which field to use?
Even if there was such a feature how could Hibernate decide which is the Map key and which columns from the Map value.
The most flexible solution is to define a DTO which will be used to hold the selected projection:
select new my.package.DTO(field1, field2, .., fieldn) from ...
And you simply pass the result to a custom result transformer, which contains the exact result set key mapping logic.
My retrived data from SQL looks like this
ID Name
1 abc
2 xyz
3 def
Which Java collection variable shall I use to store and retrieve them based on postion alter.
I tried with list...But is was only including ID values,not the Name column.
Any help would be highly Appriciated
You might want to use Map collection which is useful to store key value pairs where Id is your key and value is your name.
Map<Long,String> map = new HashMap<Long,String>();
Like Suresh ATTA said Map is the best solution for this scenario. But in case you are going to get more columns from the DB, then it is better if you write a class around it.
An object of that class will represent a row, and the list of object will represent the result set you queried for.
For your current scenario it looks like:
class Name {
String ID;
String Name;
}
List<Name> allNames = // query from DB and resultset mapped to classes properly.
allNames.get(0) will give you the first row, and allNames.get(allNames.size()-1) will give you the last row.
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.