Error in 'and' method of Hibernate Criteria - java

Hello,I am new to Hibernate and i was trying to execute and() method in Hibernate Criteria Queries using Eclipse but the LogicalExpression will show error like
The method and(Criterion, Criterion) in the type Restrictions is not applicable for the arguments (Criteria, Criteria)
package actions;
import java.util.Iterator;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.criterion.LogicalExpression;
import org.hibernate.criterion.Restrictions;
public class Andrestriction {
public static void main(String[] args) {
// TODO Auto-generated method stub
SessionFactory sf=new Configuration().configure().buildSessionFactory();
Session sn=sf.openSession();
Criteria cr=sn.createCriteria(PC.class);
Criteria id=(Criteria) Restrictions.gt("id",11);
Criteria os=(Criteria) Restrictions.ilike("os","d%");
LogicalExpression and=Restrictions.and(id,os); //This line will show error like this:-
//The method and(Criterion, Criterion) in the type Restrictions is not
//applicable for the arguments (Criteria, Criteria)
cr.add(and);
List l=cr.list();
Iterator itr=l.iterator();
while(itr.hasNext())
{
PC p=(PC)itr.next();
System.out.println(p.getId()+"\t"+p.getName()+"\t"+p.getOs());
}
sn.close();
}
}
I want to use and criteria in my Query.Please tell me how to Solve this problem.
Thanks in advance

Restrictions.gt() returns a SimpleExpression which is a Criterion (implements Criterion)
So you should not cast a SimpleExpression to a Criteria. You already have a criteria ( You create one criteria which actually transforms into a query and executed on database ), so what you need is:
Criteria cr=sn.createCriteria(PC.class);
Criterion id=Restrictions.gt("id",11); // No need to cast as SimpleExpression implements Criterion
Criterion os= Restrictions.ilike("os","d%");
LogicalExpression and=Restrictions.and(id,os);
cr.add(and);
A compiler error shows up because you are passing two Criteria objects to and() method of Restriction class but it expects Criterion objects. So change it as above and you are good to do.

As the error message indicates there is no matching Restrictions.and method with the given signature. When encountering these type-errors the first place that should be consulted is the documentation - then work back resolving the expected/actual types.
To fix this, drop the (invalid) cast and use the correct type for the variable;
// Criterion, not Criteria - also no cast
Criterion id = Restrictions.gt("id",11);
Criterion os = Restrictions.ilike("os","d%");
// Now it matches `and(Criterion, Criterion)`
LogicalExpression and = Restrictions.and(id, os);
Criteria (or criterions) are a collection of criterion; but modern English usage is a bit lax.

Related

trying to set a member ArrayList using reflection

I am trying to modify an object with an Arraylist of objects using reflection.
I understand that I cannot get the type of the objects in the ArrayList, but I (think) I am using an annotation to handle that part. I am setting the field accessibility.
I am declaring the list of stuff in the class using annotations.
#TableAnnotation(type = PhoneNumber.class)
protected List<PhoneNumber> phoneNumbers = new ArrayList<>();
#TableAnnotation(type = Address.class)
private List<Address> addresses= new ArrayList<>();
private List<Role> roles= new ArrayList<>();
... Later in the same class I try to set them:
public void setMemberTable(List<Table> tables, String memberName) throws IllegalAccessException {
Class t = getClass();
for (Field field : getClass().getDeclaredFields()) {
if (field.getName() == memberName) {
field.setAccessible(true);
List array = (List)field.get(this.getClass()); <<<=========== Here is where it is throwing
ArrayList arrayList= (ArrayList)field.get(this.getClass());
//array.add(tables.get(0));
System.out.println();
}
}
}
Here is the Annotation that seems to be working:
package com.test.database.helpers;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
#Documented
#Target(ElementType.FIELD)
#Inherited
#Retention(RetentionPolicy.RUNTIME)
public #interface TableAnnotation {
Class< ?> type();
boolean allowNull() default false;
}
This throws:
java.lang.IllegalArgumentException: Can not get java.util.List field com.test.database.entities.Person.phoneNumbers on java.lang.Class
I tried making the member variable public, but that had no affect.
I need help to be able to set the member variables in setMemberTable().
(List)field.get(this.getClass());
The .get method on j.l.reflect.Field requires the instance that you want to get the field from. You're passing the class. Which is an object of type java.lang.Class, which, of course, does not have this field, and therefore, you can't get the value of it. You want this instead.
Actually, none of this makes sense, you're right there, just read your own field. I assume this is test code, but if not, none of this makes sense in the first place.
You ask the wrong object for the value of the field.
When you write
field.get(this.getClass())
you try to get the value that the (reflected) field has on some instance. The object that you pass to retrieve the value from is this.getClass() which is an instance of java.lang.Class - and java.lang.Class has no field (for example) "phoneNumbers".
To retrieve a field from your instance you must write
field.get(this)
But then, the commented out line
array.add(tables.get(0));
doesn't make any sense. Why do you try to add an element from the tables list (which is an instance of Table) to a list of (for example) "phoneNumbers", which is a list of PhoneNumber?
And your claim that the annotation works: I don't see that annotation used anywhere in your code, so it is hard to say whether it works or not...

Not able to mock a method with List type argument

I have a method like this
public int[] processData(List<Data> dataList){
//business logic
}
And I have used the following way to mock it
when(processData(anyList())).thenReturn(new int[]{1,1});
and
when(processData(Mockito<Data>.anyList())).thenReturn(new int[]{1,1});
but nothing works.
I am using spring boot with Java 11 and Mockito 3.1
Is there any other way to mock the same?
Mockito leverages equal() as legacy method for verification/matching of argument values.
In some cases, user needs more flexibility during the verification of argument values, so it's better to use argument matchers instead of equal() method.
Note :
eq(obj) checks that the argument equals obj according to its equals method. This applies even if you pass real values without using matchers.
equals() method demands that for two lists to be equal, they must contain same elements in the same order.
In case of two list, Type of your lists should match.
Refer to doc for details : https://docs.oracle.com/javase/6/docs/api/java/util/List.html#equals%28java.lang.Object%29
Your example works for me:
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.Mockito.when;
#ExtendWith(MockitoExtension.class)
public class Test {
#Mock
A a;
#org.junit.jupiter.api.Test
public void t1() {
when(a.processData(anyList())).thenReturn(new int[]{1,1});
System.out.println(Arrays.toString(a.processData(new ArrayList<>())));
}
}
interface Data {}
interface A {
int[] processData(List<Data> dataList);
}
This prints: [1, 1]
You can try to use when(processData(mock(List.class)).thenReturn(new int[]{1,1}) but your variant when(processData(anyList())).thenReturn(new int[]{1,1}) works for me too.

Does setDefaultHighRepJobPolicyUnappliedJobPercentage(100) really work?

According to https://cloud.google.com/appengine/docs/java/tools/localunittesting#Writing_HRD_Datastore_Tests, "If your app uses the High Replication Datastore (HRD), you may want to write tests that verify your application's behavior in the face of eventual consistency. LocalDatastoreServiceTestConfig exposes options that make this easy." You're supposed to set setDefaultHighRepJobPolicyUnappliedJobPercentage(100) and then, "By setting the unapplied job percentage to 100, we are instructing the local datastore to operate with the maximum amount of eventual consistency. Maximum eventual consistency means writes will commit but always fail to apply, so global (non-ancestor) queries will consistently fail to see changes."
However, I don't think setDefaultHighRepJobPolicyUnappliedJobPercentage(100) works.
If it did, then my test case below, testEventualConsistency() should pass but it it fails on the second assertion. On the first assertion, I read back an object I've saved using an Objectify ancestor() query. It works as documented because the object is retrieved. However, the second assertion fails. In that assertion I've also read back the object I've saved but I haven't used an Objectify ancestor() query so it shouldn't retrieve anything because I've specified that no jobs should complete (i.e. the setDefaultHighRepJobPolicyUnappliedJobPercentage(100) setting).
EventualConsistencyTest Test Case
import static com.googlecode.objectify.ObjectifyService.begin;
import static com.googlecode.objectify.ObjectifyService.ofy;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import java.util.List;
import org.junit.Test;
import com.google.appengine.tools.development.testing.LocalDatastoreServiceTestConfig;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
import com.googlecode.objectify.ObjectifyService;
import com.googlecode.objectify.Ref;
import com.googlecode.objectify.util.Closeable;
import com.netbase.followerdownloader.model.DownloadTask;
import com.netbase.followerdownloader.model.User;
public class EventualConsistencyTest {
private final LocalServiceTestHelper helper =
new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig()
.setDefaultHighRepJobPolicyUnappliedJobPercentage(100));
#Test
public void testEventualConsistency() {
helper.setUp();
ObjectifyRegistrar.registerDataModel();
User user = new User();
user.id = 1L;
Closeable closeable1 = begin();
ofy().save().entity(user);
closeable1.close();
Closeable closeable2 = begin();
DownloadTask downloadTask = new DownloadTask();
downloadTask.owner = Ref.create(user);
ofy().save().entity(downloadTask);
closeable2.close();
Closeable closeable3 = ObjectifyService.begin();
List<DownloadTask> downloadTasks1 = ofy().load().type(DownloadTask.class).ancestor(user).list();
assertThat(downloadTasks1.size(), equalTo(1));
closeable3.close();
Closeable closeable4 = ObjectifyService.begin();
List<DownloadTask> downloadTasks2 = ofy().load().type(DownloadTask.class).list();
assertThat(downloadTasks2.size(), equalTo(0)); // THIS SHOULD PASS IF setDefaultHighRepJobPolicyUnappliedJobPercentage(100) WORKED
closeable4.close();
helper.tearDown();
}
}
User Definition
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
#Entity
public class User {
#Id public Long id;
public User () {
}
}
DownloadTask Definition
import com.googlecode.objectify.Ref;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
import com.googlecode.objectify.annotation.Parent;
#Entity
public class DownloadTask {
#Id public Long id;
#Parent public Ref<User> owner;
public DownloadTask() {
}
}
Environment:
appengine-api-1.0-sdk-1.9.17.jar
appengine-testing-1.9.17.jar
appengine-api-stubs-1.9.17.jar
junit-4.11.jar
objectify-5.1.3.jar
In case I missed anything else important, here is a more exhaustive list:
My questions are:
Is setDefaultHighRepJobPolicyUnappliedJobPercentage(100) broken?
Does setDefaultHighRepJobPolicyUnappliedJobPercentage(100) not really work as documented? Does it in fact apply the job even though the documentation says it's not supposed to?
Is the value passed to setDefaultHighRepJobPolicyUnappliedJobPercentage() really supposed to be 100 and not maybe let's say, 1.0f?
Do Objectify ancestor queries not really work as documented?
The problem is explained by an observation at https://cloud.google.com/appengine/docs/java/tools/localunittesting#Java_Writing_High_Replication_Datastore_tests :
"In the local environment, performing a get() of an Entity that belongs to an entity group with an unapplied write will always make the results of the unapplied write visible to subsequent global queries."
In this contect, this means the ancestor-query:
List<DownloadTask> downloadTasks1 = ofy().load().type(DownloadTask.class).ancestor(user).list();
which internally "performs a get() of an Entity that belongs to an entity group with an unapplied write" influences the behavior of the immediately-following global query:
List<DownloadTask> downloadTasks2 = ofy().load().type(DownloadTask.class).list();
To avoid your tests influencing each other, and in particular, interfering w/each other in this way, it's best to use a separate method per operation under test (each with all the needed setup and teardown parts), rather than having successive operations-under-test within a single test method.

Morphia Error : The method fromDBObject(Class<T>, BasicDBObject) in the type Morphia is not applicable for the arguments (Class<Suite>, DBObject)

I have written a code which has Suite information with Test case information embedded inside it.I have written the TestCase.java and Suite.java and they seem to have no errors.But with the MongoMapper.java which I have written I am getting this error.
The method fromDBObject(Class, BasicDBObject) in the type Morphia is not applicable for the arguments (Class, DBObject).Kindly help me with this as well as suggest me how to see whether I have my collections updated in the MongoDB Shell.Thanks in advance.Here is my code.
package com.DrAssist.Morphia.model;
import com.google.code.morphia.Morphia;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.Mongo;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.net.UnknownHostException;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
public class MongoMapper {
Morphia morph;
Mongo mongo;
DBCollection DrAssistReport;
#Before
public void setUp() throws UnknownHostException {
morph = new Morphia();
mongo = new Mongo("127.0.0.1", 27017);
// This is where we map Persons and addresses
// But shouldn't the annotation be able to handle that?
morph.map(Suite.class).map(TestCase.class);
DB testDb = mongo.getDB( "test" );
DrAssistReport = testDb.getCollection("DrAssistReport");
}
#Test
public void storePersonThroughMorphiaMapping () {
Suite suite = new Suite(new TestCase("1",new String[]{"Test1", "Test2", "Test3", "Test4"},"1","5","6","7","889"));
suite.setSID("1");
suite.setsuiteName("Suite1");
suite.setnoOfTests("5");
DrAssistReport.save(morph.toDBObject(suite));
Suite suite2 = morph.fromDBObject(Suite.class, DrAssistReport.findOne());
assertNotNull(suite2.getSID());
}
}
The ERROR I am getting is The method fromDBObject(Class, BasicDBObject) in the type Morphia is not applicable for the arguments (Class, DBObject)
It looks like you're using a version of Morphia from before this change: http://code.google.com/p/morphia/issues/detail?id=15
You could try either casting the return value from DrAssistReport.findOne() to a "BasicDBObject" or upgrade the verison of Morphia that you're using to a version whose Morphia.fromDBObject method takes a DBObject rather then requiring a BasicDBObject.

Dynamically set List<type>

I have previously only used reflection to do things like dynamically get class and set field values in it. My Google search showed me that I could also possibly use reflection for dynamic type casting?
My code is as follows:
import entity.Shipvia;
import entity.Route;
import java.lang.reflect.Field;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.Persistence;
import javax.persistence.Query;
public class RetrieveResultList {
public static List retrieveResultList(String tablename) {
EntityManager entityManager = Persistence.createEntityManagerFactory("EntityLibraryPU").createEntityManager();
Query query = entityManager.createNamedQuery(tablename + ".findAll");
List<Shipvia> resultList = query.getResultList();
return resultList;
}
}
I am using this method to dynamically retrieve result from a database table. Because the table name is always different, I cannot have List as it will be different for each table.
How would I go about converting the tablename string that I am passing in, to be the type of the List?
You can't do that and even if you could, it would be useless as all generics information is removed from the Java code when it's compiled, only casts would be there and as you would be using reflection there would be no casts to be made.
The closest thing you will be able to do is, instead of sending in a String send a Class object. The caller code would have to say which class it wants (the caller probably knows what kind of object it's using) and you would use it to make the list have the correct generic.
A very simple implementation would be something like this:
List<Shipvia> shipvias = RetrieveResultList.retrieveResultList( Shipvia.class );
And implementation could be something like this:
public class RetrieveResultList {
private static final EntityManagerFactory FACTORY = Persistence.createEntityManagerFactory("EntityLibraryPU");
public static <T> List<T> retrieveResultList(Class<T> type) {
EntityManager entityManager = FACTORY.createEntityManager();
String tablename = type.getName(); // figure out table name from **type**
Query query = entityManager.createNamedQuery(tablename + ".findAll");
List<T> resultList = query.getResultList();
entityManager.close();
return resultList;
}
}
And then you should have something like what you're looking for.
ALSO, DO NOT create an entity manager factory on every call to this method, the entity manager factory MUST BE a singleton in your project as it's a very expensive object to create. You should also close the EntityManager you created before leaving the method.

Categories

Resources