I have used below code in hibernate stuts2 java.
String hql = "from PostDetails";
Query postDetails = session.createQuery(hql); // Got warning from here
List<PostDetails> result = postDetails.list();
Warning is : Type safety: The expression of type List needs unchecked conversion to conform to List<PostDetails>
If I used this annotation #SuppressWarnings("unchecked") then warning is solved. But I don't want to any annotation.
How to fixed this warning?
I don't believe you can. Even the documentation and examples for Hibernate use a raw-type List as opposed to a typed one. However, it is very unlikely that you will run into an error with that list; Hibernate wouldn't return a list that isn't valid in that context.
The newer, standard version of the JPA API has typed queries which would avoid those warnings, and allow you to get back a properly typed list.
That would mean you could execute this to get the list that you want:
List<Student> = em.createQuery("select s from School s", Student.class).getResultList();
Related
When I try to do a TypedQuery of a type that is generic, I get a unchecked type conversion warning from Eclipse.
I am using a generic here because in the dataset, every year has to be separated into a different table due to time constraints on queries and edits. There are 118 years of data in the table (since 1900), and I would like to build a system that can extend itself every year using the Java Reflections API. However, this means that prior to compilation, my parent classes don't know which child class or table they will be operating on.
Here is an example of some code that will cause an unchecked warning even though I'm specifying what type everything is through a TypedQuery. The code I have will compile and run just fine on my database.
public class MyParentRepository<T extends MyParentPojo>
{
#PersistenceContext
private EntityManager em;
private Class<T> tea;
public MyParentRepository(Class<T> tea)
{
this.tea = tea;
}
public void giveWarning(int year)
{
String sql = String.format("SELECT * FROM mytable%d t", year);
TypedQuery<T> resultSet = (TypedQuery<T>) em.createNativeQuery(sql, tea);
}
}
The expected result is that since tea is guaranteed to be instantiated with the generic type , as it's the same type everywhere and once instantiated it can't be changed, so the compiler should understand that the Entity Manager is going to return a TypedQuery of type as well. However, it results in an unchecked type warning even though it's guaranteed to work.
I've seen people suggest fixing an unchecked type warning by going from a Query to TypedQuery, but that isn't helping in this case. Is there a way to avoid this warning while still doing what I am trying to do?
In response to an answer that was deleted, I would like to clarify something.
em.createQuery(String)
em.createQuery(String, Class<T>)
em.createNativeQuery(String)
em.createNativeQuery(String, Class)
Of these options, the first takes in a JPQL string and returns a
generic Query.
Option 2 takes in a JPQL string and a specific class representing a table
row, and returns a TypedQuery.
Option 3 takes in a SQL string and returns a generic Query.
Option 4 takes in a SQL string and a specific class representing a table row,
and why does it return a generic Query and not a TypedQuery?
It seems to me that if I am giving it a POJO of the appropriate type, option 4 should figure out how to serialize it like Option 2 does for me. In fact it does, but it doesn't set the type correctly like Option 2. This is not acceptable from my point of view since not every SQL query can be represented by a JPQL query, so there may be times I need to use SQL, and I would expect to have a TypedQuery returned.
I've solved the warning I had by switching to option 2, but I still would like to know the answer in case as I said, a situation arises where I cannot use Option 2 in the future.
Its because createNamedQuery returns Query not TypedQuery<T> even in "typed result" variant.
https://docs.oracle.com/javaee/7/api/javax/persistence/Query.html
I'm using native sql to retrieve data from db. I'm getting list of Object[].
List<Object[]> objectList = session.createSQLQuery(query).setParameter("customerId", customerId).list();
I'm getting below warning
Type safety: The expression of type List needs unchecked conversion to
conform to List
How to fix this ?
This is probably because the API you are using doesn't support generics. Consider upgrading to the latest version or using a #SuppressWarnings.
You should of course use #SuppressWarnings only if you are absolutely certain if the query return the proper type.
Also you should always document the reason for suppressing the warning as well, if possible.
When using an api doesn't support generics returns a paramterized type the type argument must be treated being a wildcard.
List<?> objectList = session.createSQLQuery(query).setParameter("customerId", customerId).list();
The above will compile without a warning. Obviously this isn't the type you want though. So you have to test the cast item by item as, technically, a List<?> could contain anything.
for(Object object : objectList){
if(object instanceof Object[]){
//Do stuff.
}
}
Now in practice if you know ahead of time what the return type should be you can just suppress the warning and carry on. Just know that if you are wrong, you'll get the cast exception thrown at the code that accesses the list rather than at the code that performed the incorrect "cast" on the list as a whole.
Using JPA 2 with EclipseLink implementation.
I'm trying to build a dynamic query which should bring me some records persisted after a given date.
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Event> criteria = builder.createQuery(Event.class);
Root<Event> root = criteria.from(Event.class);
criteria.select(root);
criteria.distinct(true);
List<Predicate> predicates = new ArrayList<Predicate>();
//...
if (dateLimit != null){
ParameterExpression<Date> param = builder.parameter(Date.class, "dateLimit");
predicates.add(builder.lessThanOrEqualTo(root.get("dateCreated"), param));
}
lessThanOrEqualTo() and le() are the only two methods in the API which look like may help me in this case. This warning is thrown by the eclipse though:
Bound mismatch: The generic method lessThanOrEqualTo(Expression<? extends Y>, Expression<? extends Y>)
of type CriteriaBuilder is not applicable for the arguments (Path<Object>, ParameterExpression<Date>).
The inferred type Object is not a valid substitute for the bounded parameter
<Y extends Comparable<? super Y>>
I can imagine that I'm not taking the correct approach for this problem but I can't find anywhere some tips or pointers for a possible solution.
The problem is that with the string-based API it cannot infer the type for the result value of the get-Operation. This is explained for example in Javadoc for Path.
If you use
predicates.add(builder.lessThanOrEqualTo(root.<Date>get("dateCreated"), param));
instead, it will work fine, because it can figure out the return type from the type argument and will find out that it is comparable. Note, the use of a parameterised method invocation root.<Date>get(...) (see, e.g., When is a parameterized method call useful?).
Another (in my opinion better) solution is to use the metamodel based API instead of the string-based one. A simple example about canonical metamodel is given for example here. If you have more time to invest, this is a good article about static metamodel: Dynamic, typesafe queries in JPA 2.0
You need to use the generated metamodel to access the attributes is a really safe way. If you use Strings to refer to your attributes, types can only be deduced from the explicit generic type used when calling the method, or by a type cast, or by the automatic type inference done by the compiler:
Path<Date> dateCreatedPath = root.get("dateCreated");
predicates.add(builder.lessThanOrEqualTo(dateCreatedPath, dateLimit));
I was getting a similar error but with the syntax predicates.add(cb.greaterThan(article.get(Article_.created), since)); and found this page. The cause for me, turned out to be that I had upgraded my project from Java 1.7 to 1.8, and in the process had configured Maven to compile for Java 1.8 as well. I simply had to change Maven compiles back to 1.7, while keeping the rest of the project at 1.8, to fix the error.
I had the same problem, when I have worked with predicates. It worked great with all types except Date type. I tried all method and most simple way for me was:
predicates.add(builder.greaterThanOrEqualTo(root.get(criteria.getKey()), (Date)criteria.getValue()));
I added (Date) before criteria.getValue(), what help to recognize my value Object as Date type.
I want to use generics in Java/Hibernate.
This is how some of the books that I've been studying have been doing it:
List messages = session.createQuery("from Message").list();
System.out.println("Found " + messages.size() + " message(s).");
I don't like that approach. I prefer using generics.
List<Message> messages = session.createQuery("from Message").list();
System.out.println("Found " + messages.size() + " message(s).");
But then again, I still get the "yellow" warning messages on my editor.
Eclipse recommends that I either suppress the warning by using #SuppressWarnings or infer generic type arguments. I'm not really sure what the latter means. But which one of the options is becoming the preferred approach to handling generics with Hibernate?
The method Query#list() unfortunately does return a raw list in Hibernate version 3.5.6-Final. This means, that you are not able to assign the result of this method to a variable of type List<Message> without a compiler warning. The only generic type you can assign the result to is List<?>. Eclipse just always suggests the infer type arguments option.
That being said, unlike Eclipse which always uses method scoping, I suggest the assignment scope SuppressWarnings annotation for clean code:
// Call to a raw method
#SuppressWarnings("unchecked")
List<Message> messages = session.createQuery("from Message").list();
To retrieve data from database using Hibernate, I use the following syntax :
Query query = session.createQuery("from User where name=? and password=?");
query.setString(0,user.getName());
query.setString(1,user.getPassword());
List list = query.list(); // Line 1
Line 1 shows warning: "List is a raw type. References to generic type List should be parameterized."
Now, if I add generics using:
List<User> list = (List<User>) query.list();
This again gives warning: "Unchecked type conversion."
How do I check the type of List of Users?
I am not sure but seems okay to me .
You might want to use
#SuppressWarnings (value="unchecked")
The information about template parameter type is erased in runtime. This is called type erasure. So, you just have to know in advance the type you are casting to. To avoid compiler warning, you may use #SuppressWarnings("unchecked").
Also, you may try the Hibernate Typesafe Criteria, have a look here.