Getting Error while using Generic Dao in room with java - java

when I try to use Generic Dao in android Room I get this Erro :
Cannot use unbound generics in query methods. It must be bound to a type through base Dao class.
import android.arch.lifecycle.LiveData;
import android.arch.persistence.room.Dao;
import android.arch.persistence.room.Delete;
import android.arch.persistence.room.Insert;
import android.arch.persistence.room.RawQuery;
import android.arch.persistence.room.Update;
import java.util.List;
#Dao
public interface BaseDaoAccess<T> {
#Insert
Long Insert(T entity);
#Update
void Update(T entity);
#Delete
void Delete(T entity);
#RawQuery
LiveData<List<T>> RowQuery(String query);
}

Due to type erasure, Java can't tell at runtime what T you mean. You can provide this information by creating a subtype that has the T bound to a specific type, such as this:
public interface CarDao extends BaseDaoAccess<Car> { }

Related

Android DAO adding a query "'#Query not applicable for field"

Here is a DAO i have created for a rooms library with a list of participants. The data is very simple.
package com.example.tag;
import androidx.lifecycle.LiveData;
import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.Query;
import androidx.room.Update;
import java.util.List;
#Dao
public interface ParticipantDAO {
#Query("SELECT * FROM Participants ORDER BY Name")
LiveData<List<Participant>> getAllParticipants();
#Query("SELECT * FROM Participants LIMIT 1")
Participant[] getAnyParticipant;
#Insert
void insert(Participant participant);
#Update
void update(Participant participant);
#Delete
void delete(Participant participant);
#Query("DELETE FROM Participants")
void deleteAll();
}
The problem is with the second #Query statement (getAnyParticipant). I receive the error: "'#Query' not applicable to field".
I am attempting to modify the android tutorials for my needs (using participants instead of words) located here: https://codelabs.developers.google.com/codelabs/android-training-room-delete-data/index.html?index=..%2F..android-training#2
What am I doing wrong?
Only method can be annotated with #Query. Here, you are trying to annotate a class field with #Query. You missed a pair of parentheses.

Compilation error using Java generics and interfaces

I'm attempting to make a Repository interface, that our business logic can use, with the idea that if we decide to change the data source that backs the repositories, that the business logic would not be affected. We have many clients that would be using this library, so we have begun making a suite of controllers that can be reused among clients. This is the repository interface:
package //redacted
import java.util.Collection;
import java.util.List;
public interface Repository<T extends Object, R extends RepositoryQuery<T>> {
T add(T entity);
Collection<T> add(Collection<T> entities);
void remove(T entity);
Collection<T> getAll();
T get(Integer id) throws InvalidEntryException;
List<T> get(Collection<Integer> ids);
List<T> query(R query);
List<T> query(T query);
}
This is the controller I'm having problems with:
package //redacted
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import /* redacted */.entities.pointbank.PointBankBalance;
import /* redacted */.entities.user.User;
import /* redacted */.queries.PendingPointsBalance;
import /* redacted */.repository.Repository;
import /* redacted */.repository.RepositoryQuery;
public class RetrievePendingPointBalance {
private Repository<PointBankBalance, ? extends RepositoryQuery<PointBankBalance>> repository;
private Constructor<? extends PendingPointsBalance> pendingQuery;
public RetrievePendingPointBalance(Repository<PointBankBalance, ? extends RepositoryQuery<PointBankBalance>> repository,
Constructor<? extends PendingPointsBalance> pendingQuery) {
this.repository = repository;
this.pendingQuery = pendingQuery;
}
public PointBankBalance execute(User user) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
PendingPointsBalance query = pendingQuery.newInstance();
query.setUser(user);
return repository.query(query).get(0);
}
}
I'm trying to create RepositoryQuery, which is what will be responsible for handling more than just CRUD operations. Here is the interface for that:
package //redacted
import java.util.List;
public interface RepositoryQuery<T extends Object> {
List<T> execute();
}
The idea there, is that each query can extend can extend the interface with setters for the parameters it will need. Then each implementation can extend that query interface with specifics of what it will need (example: setJdbcTemplate(...) )
On the controller above though, the line:
return repository.query(query).get(0);
is a compilation error, and I do not know why. Is my approach inherently flawed, or am I just missing something?
Full Error:
[ERROR] /Users/redacted/src/main/java/com/redacted/controllers/RetrievePendingPointBalance.java:[26,28] no suitable method found for query(com.redacted.queries.PendingPointsBalance)
method com.redated.repository.Repository.query(capture#1 of ? extends com.redated.repository.RepositoryQuery<com.redacted.entities.pointbank.PointBankBalance>) is not applicable
(argument mismatch; com.redacted.queries.PendingPointsBalance cannot be converted to capture#1 of ? extends com.redacted.repository.RepositoryQuery<com.redacted.entities.pointbank.PointBankBalance>)
method com.redacted.repository.Repository.query(com.redacted.entities.pointbank.PointBankBalance) is not applicable
(argument mismatch; com.redacted.queries.PendingPointsBalance cannot be converted to com.redacted.entities.pointbank.PointBankBalance)
And my error from Eclipse:
Edit: PointBankBalance interface
package //redacted
import com./* redacted */.entities.pointbank.PointBankBalance;
import com./* redacted */.entities.user.User;
import com./* redacted */.repository.RepositoryQuery;
public interface PendingPointsBalance extends RepositoryQuery<PointBankBalance> {
void setUser(User user);
}
Your problem is that the method takes an R and you defined R as ? extends RepositoryQuery<PointBankBalance> in the repository field declaration. It's uncertain which subclass ? refers to, so the compiler won't let you use a specific one. You could potentially set that field to an instance of Repository<PointBankBalance, AnotherPointsBalance>, in which case PendingPointsBalance wouldn't be a valid argument to its query method.
One way to fix it would be replacing Repository<PointBankBalance, ? extends RepositoryQuery<PointBankBalance>> with Repository<PointBankBalance, PendingPointsBalance>.
Or you could simplify things by removing the R parameter entirely:
public interface Repository<T extends Object> {
...
List<T> query(RepositoryQuery<T> query);
List<T> query(T query);
}
Then just replace Repository<PointBankBalance, ? extends RepositoryQuery<PointBankBalance>> with Repository<PointBankBalance>.

Concern about importing class implementation into DAO

I have to implement DAOs which use only the interfaces of the objects. Now I'm having trouble figuring out how to use the em.find()of the EntityManagerclass.
My specific question is, if it is ok to import the implementation of a class directly into the DAO like in this example:
import dao.IStreamingServerDAO;
import model.IStreamingServer;
import model.impl.StreamingServer;
import javax.persistence.EntityManager;
public class StreamingServerDAO implements IStreamingServerDAO {
protected EntityManager em;
public StreamingServerDAO(EntityManager em) {
this.em = em;
}
#Override
public IStreamingServer findById(Long id) {
return em.find(StreamingServer.class, id);
}
}
I feel like I'm hurting some privacy principles by simply importing the model.impl.StreamingServer class into the DAO.
Problem is I don't know how else I'm supposed to get the needed class for the em.find()method.
Please not that I can't change the return type of the findByIdmethod as it's defined like this by the interface. (Also this implementation right now works as expected).

EclipseLink JTA Persistence issue (Null Pointer Exception)

I have two entities working in Mater Detail pattern like i describe in:
Stackoverflow Post: jpa-eclipselink-onetomany-derived-ids-fail
The pattern works as expected with LOCAL RESOURCE, but when i try to move the example to a web environment GlassFish4.1 (JSF) with JTA, i get the following error:
Advertencia: DTX5014: Caught exception in beforeCompletion() callback:
java.lang.NullPointerException at entidades.OrderItemPK._persistence_set(OrderItemPK.java)
The source code for persistence class:
import java.util.List;
import javax.persistence.Query;
import javax.persistence.EntityManager;
import java.util.List;
import javax.persistence.Query;
import javax.persistence.EntityManager;
public abstract class AbstractFacade<T> {
private Class<T> entityClass;
protected abstract EntityManager getEntityManager();
public AbstractFacade(Class<T> entityClass) {
this.entityClass = entityClass;
}
public void create(T entity) {
getEntityManager().persist(entity);
}
public T edit(T entity) {
return getEntityManager().merge(entity);
}
public void remove(T entity) {
getEntityManager().remove(getEntityManager().merge(entity));
}
I tried with both methods create and edit. Any idea what I'm doing wrong, suggestions are welcome.
Your entity is using the basic 'long' types which do not allow null, so check that your database values are not null. If they are, a quick fix is to change the to the wrapper type "Long": http://edwin.baculsoft.com/2012/02/nullpointerexception-when-using-jpa/
If that is the case, you will need to track down how the database is being populated with null values for fields associated to the primary key.
The problem was in the PK class, change the data type int to Integer and then the error appeared on the method hashCode()

pattern to transfer search model to dao

We have a dao as a project (jar file).
Clients use its interfaces and factories to operate with database.
Alongside with standard CRUD operations, dao allows you to search an entity by some search criteria.
What is the best way to represent this criteria?
Is transfer object appropriate pattern in this situation?
How should client create SearchModel instance?
Please, share.
Regards.
I usually use a generic DAO:
package persistence;
import java.io.Serializable;
import java.util.List;
public interface GenericDao<T, K extends Serializable>
{
T find(K id);
List<T> find();
List<T> find(T example);
List<T> find(String queryName, String [] paramNames, Object [] bindValues);
K save(T instance);
void update(T instance);
void delete(T instance);
}
This allows me to use named queries with bound parameters and query by example. I've found it to be flexible enough to satisfy most of my needs.

Categories

Resources