in hibernate to create criteria we use
Criteria criterea=session.createCritera(SomeClass.class)
It may be available in some other examples too but I am not able to understand the structure of these type of methods.
NOTE this is an example I am trying to put to understand use of SomeClass.class like arguments
my question here is what is purpose of SomeClass.class ? why do we need it, what is the advantages of using it as argument.
Edit its not a duplicate but have string connection to this question
What is this .class syntax?
If you attach .class to the end of a class name, you get the Class<T> object corresponding to the class.
Examples:
String.class returns an instance of Class<String>
Integer.class returns an instance of Class<Integer>
What can you do with a class object
Reflection! If you have access to a class object, you can do all kinds of cool stuff! You can call methods, get and set values of fields...
Why is this used in Hibernate?
I haven't used hibernate before, but this syntax is used in other libraries as well, especially in ORMs or JSON serializers. I'll use JSON serializers as an example as I'm more familiar with those.
In a JSON serializer, you need to give it a class object because it needs to get all the fields that you want to serialize to JSON. It uses reflection to get and set the values of those fields, then convert them to JSON. When it deserializes JSON, it finds the field that needs to be set with the name in the JSON. These operations require a Class object because without it, how can Java know which class should it find the field? Also, to create a new object with reflection, a Class is needed as well!
Hibernate provides many ways to handle the objects in relation with RDBMS tables.
One way is Session interface providing createCriteria() method which can be used to create a Criteria object.
As name says criteria, it is useful to execute queries by applying filtration rules and logical conditions of programmer wish.
For example:
Criteria obj=session.createCritera(Galaxy.class) // say SomeClass is Galaxy.class
List results = obj.list();
Here, criteria query is one which will simply return every object that corresponds to the Galaxy class.
We even can restrict the results with criteria, example add() method available for Criteria object to add restriction for a criteria query.
Following is the restriction to return the records with planet which has 7.4 billion population from Galaxy class:
Criteria cr = session.createCriteria(Galaxy.class);
cr.add(Restrictions.eq(“planet”, 75000000000));
List results = cr.list();
Related
Using Spring 5.0.6 and Spring-Data-Mongo 2.0.7, I have an issue when fetching entities being transformed into the wrong class. See the following simplified scenario:
Entity setup:
public class PersistableObject {
#Id #Field("_id") private String id;
}
#Document(collection = "myapp_user")
public class User extends PersistableObject {...}
public class RealUser extends User {...}
public class VirtualUser extends User {...}
So, there is a common MongoDB collection storing both types of User, discriminated by the automatically added _class property.
Furthermore, there is a Repository into which the MongoTemplate is injected.
#Autowired
private org.springframework.data.mongodb.core.MongoTemplate template;
Everything fine, so far. Now, if I want to fetch all documents that contain a RealUser, I could call this
template.findAll(RealUser.class)
I'd expect the template to find all documents that have the discriminator property _class set to com.myapp.domain.RealUser.
But this doesn't work as expected. I even get all VirtualUsers, as well, put into objects of type RealUser with all VirtualUser-specific properties missing, and all RealUser-specific properties set to null.
Furthermore, when I go and save a User, which is actually a VirtualUser in MongoDB, but has been squeezed into a RealUser class, Spring would change the _class-property to the wrong type, magically converting a VirtualUser into a RealUser.
So both methods here would load the entire collection and squeeze all objects into the specified class, even if it is the wrong one:
template.findAll(VirtualUser.class)
template.findAll(RealUser.class)
This behavior is probably not desired, or if so, then it is extremely misleading and harmful. You can easily shred your whole data with this.
Can anyone shed some light on this?
I've created a ticket at Spring's Jira. Find Olivers comment below:
The method actually works as expected but I agree that we need to
improve the JavaDoc. The method is basically specified as "Load the
documents the given type is configured to persisted in and map all of
them (hence the name) to the given type". The type given to it is not
used as a type mapping criteria at the same time. Every restriction
you want to apply on the documents returned needs to be applied
through a Query instance, which exposes a ….restrict(…) method that
allows to only select documents that carry type information.
The reason that findAll works the way it works is that generally
speaking – i.e. without an inheritance scenario in place – we need to
be able to read all documents, even if they don't carry any type
information. Assume a collection with documents representing people
that have not been written using Spring Data. If a
findAll(Person.class) applied type restrictions, the call would return
no documents even if there were documents present. Unfortunately we
don't know if the collection about to be queried carries type
information. In fact, some documents might carry type information,
some might not. The only way to reasonably control this, is to let the
user decide, which she can by either calling Query.restrict(…) or not.
The former selects documents with type information only, the latter.
As I said, I totally see that the JavaDoc might be misleading here.
I'm gonna use this ticket to improve on that. Would love to hear if
the usage of Query.restict(…) allows you to achieve what you want.
I have a interface named Customer, These two classes CustomerImpl AND OwnerCustomerImpl both implemented this interface, then I have a HQL like "select customer from Customer customer where customer.username=:username", so what's result of this HQL?
I always get objects of CustomerImpl, but I really want to get OwnerCustomerImpl.
I also read doc like:
14.8. Polymorphic queries
A query like:
from Cat as cat
returns instances not only of Cat, but also of subclasses like DomesticCat. Hibernate queries can name any Java class or interface in the from clause. The query will return instances of all persistent classes that extend that class or implement the interface. The following query would return all persistent objects:
from java.lang.Object o
The interface Named might be implemented by various persistent classes:
from Named n, Named m where n.name = m.name
These last two queries will require more than one SQL SELECT. This means that the order by clause does not correctly order the whole result set. It also means you cannot call these queries using Query.scroll().
As I think, the result should include both these two classes, so does anybody can help to explain this?
Yes, according to Hibernate, both CustomerImpl and OwnerCustomerImpl instances should be returned. Check if you have persisted instances for both of those classes.
Also check if you really implement the same Customer interface (and not one from another package).
Also check if the result is not a complete list (e.g. just the first X elements) because if the result is limited, as quoted by you Hibernate may choose to return CustomerImpl instances first that meet your criteria and include OwnerCustomerImpl after that.
Also it could be you simply don't have any OwnerCustomerImpl persisted instances that match your query condition.
i am new to MyBatis,i am unable to find tutorials to learn,present i am going to start working on MyBatis with Spring,i had used session.selectOne(String arg0, Object arg1) but i am not able to understand how it works and what it will do with the second parameter that is Object arg1.
can any one help in this.
thank you
The second argument to selectOne and selectList is for a parameter. It can be a primitive if you have very simple needs in your query, say a single integer, or for more complicated queries requiring many values to be interpolated, a bean class instance with the values populated as needed (and containing the proper getters and setters).
In your mapper file you then define the type of the parameter via the parameter attribute, and can then interpolate either inline or with escaping (the former for things that should never be escaped, such as variable table or column names, and the latter for things which should always be escaped, such as values in a WHERE clause).
See the MyBatis doc for more detail:
http://mybatis.github.io/mybatis-3/java-api.html
Response to comments from OP:
MapBuilder must be custom code related to Map data structures. There's an ImmutableMap.Builder as part of Guava, but that doesn't seem like what this is. I don't think it's related to Mybatis per se.
It looks like that code is just building up a Map object, and then passing it off to the selectOne query for use within the query definition in the mapper (instead of a custom bean class).
What's the definition on LoginMapper.getUserByUsername in your mapper? In that definition, the contents of the map object are likely being interpolated into the query so dynamic values can be included.
One of my goals is to create an engine that will set values in pojo object from JPA objects dynamically using reflection. One of the matching criteria is, that the field names should match.
I was successfully able to implement this for two pojo objects. But when I tried using JPA objects as one of the object parameter, it didn't work. Based on my research I found out that the method Class.getDeclaredFields() , does not give me the name of the field but the getter/setter method name of member variable for JPA objects.
Can anyone please give me a lead or direction as in where/what should I look to accomplish this task?
JPA providers will often use dynamic proxy classes of your concrete JPA classes, so you have no guarantee of the field names in the proxy. The only guarantee about a proxy is that the methods are the same. Use a debugger to inspect the runtime class of the JPA class instances that you're trying to use and you'll see the problem.
The best you'll be able to do is use reflection to call methods on JPA-returned objects.
All that aside, I don't really see why you'd need to POJO-ify an entity class anyway, since an entity is primarily an annotated... POJO.
One of the matching criteria is, that the field names should match.
I think that this is the root of your problem. There is simply no guarantee that a Java object's field names will match the names of getters and setters ... or anything else. If you make this assumption, you will run into cases where is doesn't work.
The best solution is to simply not use this approach. Make it a requirement that the Pojo classes conform to the JavaBeans spec and rely on the setters to set the properties. This is likely to work more often than making assumptions about (private) field names.
In fact, the state of a generic JPA object implemented using a dynamic proxies could well be held in a hash map. Those fields you can see could simply be constants used for something else.
I've got a relatively simple class that is primarily backed by a Map<String,String>. I'd like to persist this class and be able search within the keys within the map. Based on this Stack Overflow question I get the feeling that Maps can only be persisted as a serialized blob.
I also see on the ORMLite website the following:
public class Account {
…
#ForeignCollectionField(eager = false)
ForeignCollection<Order> orders;
…
}
In the above example, the #ForeignCollectionField annotation marks
that the orders field is a collection of the orders that match the
account. The field type of orders must be either ForeignCollection
or Collection<T> - no other collections are supported. The
#ForeignCollectionField annotation supports the following fields:
Based on the above I get the impression that what I want isn't possible, but I thought I'd check here to be sure. I have it persisted in Hibernate, but I'd rather use something lighter like ORMLite!
One pretty easy solution is to have the getters and setters work with a JSONObject behind the scenes, and putting that object as a String in the database.
But then again, JSON isn't part of java-out-of-the-box so this may feel unneccesary if you're not using it anyway.
Yeah, there is no way in ORMLite to persist a Map. Keeping with the KISS principle, only the simple Collection class is supported. Set and Map have a lot more interface weight to them and will probably never be supported.
I don't have any super great work arounds for you. You could obviously use ForeignCollection and then have a local Map field that you create when you need to access the collection that way. Maybe an addOrder() method that would add it to the ForeignCollection and the Map.