Hibernate queries call toString() method - java

I have a list of names: List<Name>, Name has two methods:
toString() returns "Name: Tom"
getName() returns "Tom"
To query the database for persons with certain names, I'd do
// Query a single database entry
Query query = em.createQuery("FROM person WHERE name = :name");
query.setParameter("name", names.get(0).getName());
When I want to query multiple entries (using WHERE ... IN (...) I'd have to do this:
// Convert the list of name instances to a list of strings
List<String> nameStrings = new ArrayList<String>(names.size());
for (Name name : names) {
nameStrings.add(name.getName());
}
// Query multiple database entries
Query query = em.createQuery("FROM person WHERE name in (:name)");
query.setParameter("name", nameStrings); // JPA
query.setParameterList("name", nameStrings); // Hibernate
Do I have to build a second list? I'd rather do this:
// Query a single database entry
Query query = em.createQuery("FROM person WHERE name = :name");
query.setParameter("name", names.get(0));
and
// Query for multiple database entries
Query query = em.createQuery("FROM person WHERE name in (:name)");
query.setParameter("name", names); // JPA
query.setParameterList("name", names); // Hibernate

Short answer is yes, you need to build the second list. You need to provide a List of Strings (or rather a Collection), a List<Name> will never match this. I'd recommend making some kind of utility method that takes a List<Name> and return a List<String> of the names.
public static List<String> toNameStrings(List<Name> names) {
List<String> list = new ArrayList<String>(names.size());
for (Name name : names) {
list.add(name.getName());
}
return list;
}
I haven't been able to test the following, and I'm not sure I want to recommend it in any way, but I think you could make a List implementation that would return different object types depending on the state it's in. Using this you'd be able to do something like list.setStringMode(false) to use it as a List<Name> (though Generics are going out the window at this stage, they'll all be returned as Object), then list.setStringMode(true), to use it as a List<String>. It would look something like the following:
public class NameAndStringList extends ArrayList<Object> implements List<Object>
{
private boolean stringMode = false;
#Override
public boolean add(Object object)
{
return super.add(toName(object));
}
// Do the same for add(index, element)
// Do the same for set(index, element)
// Do the same for remove(object)
#Override
public boolean addAll(Collection<? extends Object> collection)
{
final List<Name> convertedCollection = new ArrayList<Name>();
for (Object object : collection)
{
convertedCollection.add(toName(object));
}
return super.addAll(convertedCollection);
}
// Do the same for addAll(index, collection)
// Do the same for removeAll(index, collection)
// Do the same for retainAll(index, collection)
#Override
public boolean contains(Object o)
{
return super.contains(toName(o));
}
// Do the same for containsAll(collection)
// Do the same for indexOf(object)
// Implement Iterator that checks the stringMode variable before returning value.
// Override all iterator methods to retrieve custom Iterator implementation.
// Override subList(fromIndex, toIndex) to make subList be an instance of NameAndStringList as well.
#Override
public Object get(int index)
{
if (stringMode)
{
return ((Name) super.get(index)).getName();
}
return super.get(index);
}
// Implement setStringMode(boolean)
protected Object toNameString(Object object)
{
if (object instanceof Name)
{
// Convert to String here
}
return object;
}
protected Name toName(Object object)
{
if (object instanceof String)
{
// Convert to Name here.
}
return object;
}
}
Note that this relies on you being able to convert a String to a Name as well as vice-versa, but you could always get rid of that bit if you know you'll always populate it yourself using Name instances. The general idea here is that the List stores Name instances, but is free to return String instances since it's a List<Object>. Again, I'm not sure I'd recommend this approach, but it should meet your requirements, or at least as close as I can get atm.

Related

sort list of beans manually without comparator

public class Organization {
protected List<Address> addresses;
protected String SourceId;
protected String organizationId;
protected String organizationName;
}
public class ReferenceOrg{
public List<Organization> getAllOrgs() {
List<Organization> listOfOrgsTemp = new ArrayList<Organization>();
List<Organization> listOfOrgs = new ArrayList<Organization>();
listOfOrgsTemp.addAll(webToolWS.getAllProviders());
listOfOrgsTemp.addAll(webToolWS.getAllVendors());
for(Organization org : listOfOrgsTemp) {
listOfOrgs.add(org);
}
return listOfOrgs;
}
}
I wanted to sort listOfOrgs by organizationname, but I cannot implement comparator on my organisation class , it is used by different projects and they want to sort on differnt field. with out modifiying organisation class how can i sort listofOrgs list manually.enter code here
I just learned how to use a Comparator to sort a JTable with numeric string data with commas. I didn't try to execute my addition to your code (and had to delete some of your references to get compilation) but maybe this will help get you started. Lines flagged with or surrounded by // ******* show code to add.
public class ReferenceOrg
{
static Comparator compareOrgs; // ***********************
public List<Organization> getAllOrgs()
{
// ************************************************************
compareOrgs = (Comparator) new Comparator()
{
#Override public int compare(Object oo1, Object oo2)
{
Organization or1 = (Organization)oo1;
Organization or2 = (Organization)oo2;
String o1 = or1.organizationId;
String o2 = or2.organizationId;
return o1.compareTo(o2);
}
};
// ************************************************************
List<Organization> listOfOrgsTemp = new ArrayList<Organization>();
List<Organization> listOfOrgs = new ArrayList<Organization>();
...
for(Organization org : listOfOrgsTemp) {
listOfOrgs.add(org);
}
Collections.sort(listOfOrgs, compareOrgs); // *******************
return listOfOrgs;
}
From Javadoc:
java.util.Collections
public static <T> void sort(List<T> list, Comparator<? super T> c)
Sorts the specified list according to the order induced by the specified comparator.
All elements in the list must be mutually comparable using the specified comparator
(that is, c.compare(e1, e2) must not throw a ClassCastException for any elements e1 and e2 in the list).
This sort is guaranteed to be stable: equal elements will not be reordered as a result of the sort.
The specified list must be modifiable, but need not be resizable.
Implementation Note:
This implementation defers to the List.sort(Comparator) method using the specified list and comparator.
Parameters:
list - the list to be sorted.
c - the comparator to determine the order of the list. A null value indicates that the elements'
natural ordering should be used.

JAVA return ArrayList object from conditional

I have an interface test class that implements another super-class. In the test class I have a method that is supposed to return an object from an array list; first it's supposed to check the objects in the list to see if it is there, if it is not, it will return a null, otherwise it will return the object that is found. Here is the code I have implemented:
public class ProductDBImpl implements ProductDB {
// field declarations
ArrayList<Product> products = new ArrayList<Product>();
#Override
public Product getProduct(int productId)
{
// TODO Auto-generated method stub
// create an iterator for the Arraylist
Iterator<Product> pritr = products.iterator();
while(pritr.hasNext())
{
Product pr = pritr.next();
if (pritr.next().getId() == productId)
{
return pr;
}
else
{
return null;
}
}
}
Unfortunately I am getting the error that says:
This method must return a result of type Product.
I was under the impression that by using an iterator and cycling through each element in the list, each element is a type Product. Please help me identify my error.
Your return statements are returning a Product or null, both legal for getProduct. But what if pritr.hasNext() returns false right away, if there are no Products? There is no return statement if the while loop exits for this reason.
Add a return statement after the while loop.
Also, because you are always returning something in the first iteration of the while loop, it's not necessary for it to be a loop. You can change it to if without changing anything else.
But is that really what you want? It doesn't make sense to return null if the first product found doesn't match. You may want to consider removing that else block, to continue searching through the list (and not changing while to if).
To take care of the error, you need a return statement at the end of the while loops, as rgettman has pointed out. But you should also not be returning null from within the loop. You should only return null once your loop has completed, and no matching products have been found, as follows:
#Override
public Product getProduct(int productId)
{
Iterator<Product> pritr = products.iterator();
while (pritr.hasNext())
{
Product pr = pritr.next();
if (pritr.next().getId() == productId)
{
return pr;
}
}
return null;
}
There is logical mistake in the code you have shared. Your intention is to return the matching product if its found or null if its not. its even better to add a break if you found your product. The correct code would be..
public class ProductDBImpl implements ProductDB {
// field declarations
ArrayList<Product> products = new ArrayList<Product>();
#Override
public Product getProduct(int productId)
{
// TODO Auto-generated method stub
// create an iterator for the Arraylist
Iterator<Product> pritr = products.iterator();
Product productObj = null;
while(pritr.hasNext())
{
Product pr = pritr.next();
if (pritr.next().getId() == productId)
{
productObj = pr;
break;
}
}
return productObj;
}
If you're interested, in Java 8 this can be accomplished little differently, without the pesky "null"s and in a more declarative style.
So you want to return a product with specified id from an array list.
Since it is quite possible for the product to not be present, you could make ProductDB interface return an Optional of Product. That way the user of the interface has much clearer picture of what to expect.
Inside the get product function just get the Stream from products list, filter the elements that have desired productId and return the first.
public class ProductDBImpl implements ProductDB{
ArrayList<Product> products = new ArrayList<>();
#Override
public Optional<Product> getProduct(int productId) {
return products.stream()
.filter(p -> p.getId() == productId)
.findFirst();
}
}

how to know the data type of list

here is my code,here i am taking elements into my list. but actually i have to process on my list . so necessary to know the type of list
public class FetchNameService {
public static Infobean fetchId() {
Infobean infobean = new Infobean();
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
String query="SELECT ifnull(max(CONVERT(substring(id,4),SIGNED) ),0) as maxId FROM infotable";
Query name = session.createSQLQuery(query);
List<?> list = name.list();
System.out.println(list.get(0));
return infobean;
}
}
You can use reflection to get the type of a class.
Class clazz = list.get(0).getClass();
System.out.println(clazz.getCanonicalName());
System.out.println(clazz.getEnclosingClass());
System.out.println(clazz.getSimpleName());
Or if you know what types of classes it could resolve to you could try something like the following:
Object o = list.get(0);
if (o instanceof String)
{
...
}
else if (o instanceof Integer)
{
...
}
I think the only thing you can try is instanceOf() with well-considered assumptions since list is of the type List<Object> according to the docs.

I can't iterate through TreeSet

I have to add User identified by his id into set and in runtime all users form that set have to be sorted by this id.
I've created TreeSet added some User objects and tried to iterate through it.
Here is my attempt:
//irrelevant code removed
TreeSet<User> userSet = new TreeSet<User>();
userSet.add(new User(2));
userSet.add(new User(1));
userSet.add(new User(3));
Iterator<User> iterator = userSet.iterator();
while (iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
I wrote class User where is one of the fields id and constructor have id as parameter.
public class User {
private int id;
// irrelevant code removed
public User(int id) {
this.id = id;
}
// irrelevant code removed
public String toString() {
return id + "";
}
}
When i run this code I get ClassCastException.
Here is the stacktrace:
Exception in thread "main" java.lang.ClassCastException: OrderedUsers$User cannot be cast to java.lang.Comparable
at java.util.TreeMap.compare(TreeMap.java:1188)
at java.util.TreeMap.put(TreeMap.java:531)
at java.util.TreeSet.add(TreeSet.java:255)
at OrderedUsers.<init>(OrderedUsers.java:9)
at Main.main(Main.java:6)
What I am doing wrong?
You are on the right way when you decided to use TreeSet because with TreeSet you can get ordered output. But...
Note that if you use TreeSet, because of TreeSet is sorted you have to implement Comparable.
When you implement Comparable you will get what you expected.
I suggest that you perform changes like this:
public class User implements Comparable<User> {
private int id;
// irrelevant code removed
public User(int id) {
this.id = id;
}
// irrelevant code removed
public String toString() {
return id + "";
}
#Override
public int compareTo(User u) {
return id - u.id;
}
}
Either pass a custom Comparator to TreeSet constructor or implement Comparable in your model class
TreeSet maintains sorted order and it needs to know how Users can be compared
Here's the statement at TreeMap.java 1188:
return comparator==null ? ((Comparable<? super K>)k1).compareTo((K)k2)
: comparator.compare((K)k1, (K)k2);
So if comparator is null, then it will try to cast the set member to a (Comparable). If your class doesn't implement Comparable, this will cause the ClassCastException you saw. comparator is non-null only if you call the TreeMap constructor that provides a Comparator (or if you copy it from another SortedMap that already has a comparator).
TreeSet internally stores the object by performing comparasions with the existing ones similar to Binary Search Tree (actually its a Red-Black tree). So you need to implement interface Comparable in User or provide a custom Comparator to the TreeSet.
If you dont want the user objects to be stored in a sorted order I would recommend using ArrayList.
Method 1 :
public class User implements Comparable<User>
{
public int compare(User u)
{
if( u == null)
return 1;
return id - u.id;
}
}
Method 2 :
public class CompareUsers implements Comparator<User>
{
public int compareTo(User a, User b)
{
if(a == null)
return -1;
if(b == null)
return 1;
return a.id - b.id;
}
}
// Create an instance of this comparator class and pass to the TreeSet
// during initialization.
TreeSet<User> userSet = new TreeSet<User>(new CompareUsers());

Return an Object in Java

I've been struggling to work out how to return an object.
I have the following array of objects.
ArrayList<Object> favourites;
I want to find an object in the array based on it's "description" property.
public Item finditem(String description) {
for (Object x : favourites) {
if(description.equals(x.getDescription())) {
return Object x;
else {
return null;
Can someone please show me how I would write this code. Thanks.
Use generics:
ArrayList<Item> favourites;
public Item finditem(String description) {
for (Item x : favourites)
if(description.equals(x.getDescription()))
return x;
return null;
}
Or if you really do want to have an array of Objects, the return type of the method must be Object:
public Object findItem(String description)
but it really looks like you want favourites to be an arraylist of Items!
You can't call getDescription on a generic Object.
You want your ArrayList to be composed of a specific type of Object, that has the property description.
Since you have your class Item:
public class Item {
private String description;
public String getDescription(){
return description;
}
... other methods here
}
Now you can create an ArrayList of this type, such as:
List<Item> myList = new ArrayList<Item>();
And iterate over it the same way you're doing... almost.
Your iteration code is broken, since you'll always just check the first element, and return null if it's not what you're looking for, what you want is something like:
for (Item x : favourites) {
if(description.equals(x.getDescription())) {
return x;
return null;
Notice that this way you'll iterate over the entire list, and only if you reach the end of the cycle will you return null.
ArrayList<Item> or change return type to Object.

Categories