chiperortiz
chiperortiz

Reputation: 4991

Java Generic Type with extends and T using Hibernate

I have a simple interface like this.

public interface EntityClass
{    
    public void setId(final Integer id);    
    public Integer getId();    
}

and a class

public Student implements EntityClass

I am trying to code a class which uses a generic type T but still is a instanceof EntityClass a EntityClass subclass something like this.

public abstract class CustomizableQueriesForClazzAndFields<T extends EntityClass>

That's is the project inside that class i want a method like this.

public List<T>getMultipleClazzWithFields(final String ...fields){return of(genericType).retrieve(fields);}

private MyCriteria of(final Class<? extends EntityClass>applyToClazz){........}

MyCriteria is a wrapper over org.hibernate.Criteria.

And in my implementation would do something like this.

public final class TestCustom extends CustomizableQueriesForClazzAndFields<Student>
{
    public static void main(String[] args) 
   {
       final TestCustom clazz = new TestCustom();
       final List<Student>a=clazz.getMultipleClazzWithFields("id","name","phone");
       a.stream().forEach(clazz::consumer);
   }     
 }

Doing this code i would like to be represent it like this using generics.

public List<Student>getMultipleClazzWithFields(final String ...fields){return of(Student.class).retrieve(fields);}

But i dont know how to represent this or if it's possible.

public List<T>getMultipleClazzWithFields(final String ...fields){return of(genericType).retrieve(fields);}

Which genericType should be represent it as Student the same Student as

public final class TestCustom extends CustomizableQueriesForClazzAndFields<Student>

Or represent it as

public final class TestCustom extends CustomizableQueriesForClazzAndFields<School>

And would do something like

public List<School>getMultipleClazzWithFields(final String ...fields){return of(School.class).retrieve(fields);}

Because i was diving like this

public List<T>getMultipleClazzWithFields(final String ...fields){return of(T).retrieve(fields);}

But the compiler kicks me and says.

cannot find symbol
symbol:   variable T
location: class CustomizableQueriesForClazzAndFields<T>
where T is a type-variable:
T extends EntityClass declared in class CustomizableQueriesForClazzAndFields
----
(Alt-Enter shows hints)

I also try

public abstract class CustomizableQueriesForClazzAndFields<Class<T extends EntityClass>>

But says.

> expected
----
(Alt-Enter shows hints)

Or how i can accomplish my desire code.. any workaorund.

Because i a kind annoying passing as parameter.

UPDATE

All i wanna to do is pass a SubClass of EntityClass and creates.

session.createCriteria(genericType);

As well gives me the List but i dont know if it's possible to catch or capture the generic type pass CustomizableQueriesForClazzAndFields<Student> and passed to of() method which is who created the org.hibernate.Criteria object i cannot pass only a T value because in my graph would like to be a subclass of EntityClass a not just a raw T value.

I need to catch or capture

CustomizableQueriesForClazzAndFields<Student> 

Student generic type.

If this possible or i am dreaming sorry by my poor english.

Thank a lot and best regards from Venezuela..

Upvotes: 0

Views: 1309

Answers (1)

Thomas
Thomas

Reputation: 88707

Approach 1:

I'm not sure I fully understand your question but I have the feeling you want something like this:

public abstract class CustomizableQueriesForClazzAndFields<T extends EntityClass> {
  public List<T> getMultipleClazzWithFields(final Class<T> clazz, final String ...fields){
    return of(clazz).retrieve(fields);
  }

  private MyCriteria of(final Class<T> applyToClazz) {
     ...
  }
}

The compiler can't create/retrieve an instance of T at runtime just from inferred data, hence you have to pass that information somehow e.g. as a parameter:

List<Student> l = getMultipleClazzWithFields(Student.class, "field1", "field2");

Approach 2:

Instead of passing Class<T> as a parameter you could also create subclasses for every T, e.g. class StudentQueries extends CustomizableQueriesForClazzAndFields<Student>, and then use reflection to find out the type of T. Please note though, that this would only work for sublcasses that define the concrete type of T.

Which approach is better depends on your needs but if it's just for that query I'd pass the class of the entity as a call parameter and skip all those subclasses that would be needed otherwise.

Update: if you want to implement the second approach (subclasses) have a look here for some code on how to use reflection to look up the type of T: http://www.artima.com/weblogs/viewpost.jsp?thread=208860

Upvotes: 1

Related Questions