Question

I have a BaseDao interface to persist data to mysql using hibernate

public interface BaseDao<T extends Serializable> {
    public void saveAll(Collection<T> objects) throws PersistenceException;
}

i have an entity classes hirechy that their base class is BaseActivity (all extends serializable) one of them:

public class Activity1 extends BaseACtivity{...}

in some class i'm declaring ActivityDao:

 protected abstract ActivityDao<Activity1> createActivityDao1();

and a method:

 private void  persistData(ActivityDao<? extends BaseActivity> activityDao, Collection<? extends BaseActivity> data){
    EntityTransaction transaction = activityDao.getEntityManager().getTransaction();

    try {
        transaction.begin();

        activityDao.saveAll(data);
        transaction.commit();
    }
    catch (HibernateException ex) {

at activityDao.saveAll(data) i'm getting a compile time exception:

 Error:(62, 24) java: method saveAll in interface com.matomy.persistence.dao.BaseDao<T>
 cannot be applied to given types;
 required: java.util.Collection<capture#1 of ? extends
 com.matomy.persistence.entity.activities.BaseActivity>
 found: java.util.Collection<capture#2 of ? extends   com.matomy.persistence.entity.activities.BaseActivity>
 reason: actual argument java.util.Collection<capture#2 of ? extends     com.matomy.persistence.entity.activities.BaseActivity>
 cannot be converted to java.util.Collection<capture#1 of ? extends     com.matomy.persistence.entity.activities.BaseActivity> 
 by method invocation conversion

BaseActivity:

public abstract class BaseActivity implements Serializable, Comparable<BaseActivity> {

Help please Thanks!

Roy

UPDATE:

private <T extends BaseActivity> void  persistData(ActivityDao<T> activityDao, Collection<T> col){
    EntityTransaction transaction = activityDao.getEntityManager().getTransaction();

    try {
        transaction.begin();

        activityDao.saveAll(col);
        transaction.commit();
    }
    catch (HibernateException ex) {
Was it helpful?

Solution

The usage of two bounded wildcards with the same bound doesn't mean they are the same type. In this case, the actual type argument for ActivityDao<? extends BaseActivity> might not be same as the one coming with Collection<? extends BaseActivity>. So, the saveAll() method wouldn't work.

To elaborate further, the compiler replaces each wildcard occurrence with a unique placeholder which is nothing but capture of that wildcard. That means, Collection<?> becomes Collection<CAP#1 of ?>, similarly Collection<? extends T> becomes Collection<CAP#1 of ? extends T>. If a Collection<?> is again encountered, it will be replaced with Collection<CAP#2 of ?>.

So, your method declaration is somewhat similar to:

private void  persistData(ActivityDao<CAP#1-of-? extends BaseActivity> activityDao, Collection<CAP#2-of-? extends BaseActivity> data){
    EntityTransaction transaction = activityDao.getEntityManager().getTransaction();

    try {
        transaction.begin();

        activityDao.saveAll(data);
        transaction.commit();
    }
    catch (HibernateException ex) {
    }
}

where CAP#1 and CAP#2 are different type parameters for compiler. Of course, the signature of saveAll for that method becomes like this:

public void saveAll(Collection<CAP#1-of-? extends BaseActivity> objects) throws PersistenceException;

And since Collection<T1> is not the same as Collection<T2> for two different type arguments, so that method invocation fails.

You can resolve this issue by using generic method instead:

private <T extends BaseActivity> void persistData(ActivityDao<T> activityDao, Collection<T> data){
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top