I'm using Room for my android app. I'm now trying to setup my database, but there is an error message, which says, that the Dao class must be annotated with #Dao. But as you can see in the coding snippet, the Dao class is annotated with #Dao. Does anyone know where the problem or my mistake could be? Both files aren't in the same folder (DAO is in the service folder while the other class is in the model folder)
Device.java
#Entity(tableName = "device")
public class Device {
#PrimaryKey(autoGenerate = true)
public int device_id;
#ColumnInfo(name = "identifier")
public String identifier;
#ColumnInfo(name = "language")
public int language;
#ColumnInfo(name = "searchFilter")
public int searchFilter;
public Device(String identifier, int language, int searchFilter){
this.identifier = identifier;
this.language = language;
this.searchFilter = searchFilter;
}
}
DeviceDAO.java
#Dao
public interface DeviceDAO {
#Insert(onConflict = OnConflictStrategy.REPLACE)
void addDevicePreferences(DifficultType difficultType);
#Query("SELECT * FROM device")
List<Device> selectAllDevicePreferences();
#Update(onConflict = OnConflictStrategy.REPLACE)
void updateDevicePreferences(Device device);
}
Check your database class. When you define DAO, you must have use wrong type(Device instead of DeviceDAO).
Incorrect
public abstract Device deviceDao();
Correct
public abstract DeviceDAO deviceDao();
Hope this will work. Thanks
Error Message:
Dao class must be annotated with #Dao
To solve error please read it properly.
If this error messages shows on Model class then you need to modify your AppDatabase class. I am giving you the code what gives error then error corrected code.
Error Code:
MyImage.java
#Entity
public class MyImage {
#PrimaryKey(autoGenerate = true)
private int uid;
#ColumnInfo(name = "title")
private String title;
#ColumnInfo(name = "photo")
private String photo;
public MyImage(String title, String photo) {
this.title = title;
this.photo = photo;
}
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getPhoto() {
return photo;
}
public void setPhoto(String photo) {
this.photo = photo;
}
}
MyImageDao.java
#Dao
public interface MyImageDao {
#Query("SELECT * FROM myimage")
List<MyImage> getAll();
#Insert
void insertAll(MyImage... myImages);
#Delete
void delete(MyImage myImage);
}
AppDatabase.java
#Database(entities = {MyImage.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract MyImage myImageDao();
}
Here has error on only AppDatabase.java file, you can see myImageDao has return type MyImage, that means it assumed that MyImage is a Dao class but MyImage is model class and MyImageDao is Dao class.
So it need to modify AppDatabase.java class and MyImage to MyImageDao.
The corrected code is-
AppDatabase.java
#Database(entities = {MyImage.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract MyImageDao myImageDao();
}
For Kotlin users :
Check if you've added following line in your Database file.
abstract val myDatabaseDao:MyDatabaseDao
I was facing the same issue, after struggling for some time I realized that in the database class, I created a variable of Entity class instead of Dao class.
Check if you have any additional methods in your interface. In my Kotlin implementation I had:
#Dao interface DeviceDao {
#get:Query("SELECT * FROM extdevice")
val all: List<ExtDevice>
fun first() : ExtDevice? {
val devices = all
if (devices.isNotEmpty())
return devices[0]
return null
}
}
removing first() solved my issue:
#Dao interface DeviceDao {
#get:Query("SELECT * FROM extdevice")
val all: List<ExtDevice>
}
add
import androidx.room.Dao;
to your interface that u set querys on it and then add the first line from this code
#Dao
public interface UserDeo {
#Query("SELECT * FROM user")
List<User> getAllUsers();
#Insert
void insertAll(User... users);
}
Your syntax look correct by what i can tell. Have you tried the following things:
Are your imports complete?
import android.arch.persistence.room.Dao;
import android.arch.persistence.room.Delete;
import android.arch.persistence.room.Insert;
import android.arch.persistence.room.OnConflictStrategy;
import android.arch.persistence.room.Query;
import android.arch.persistence.room.Update;
Mabe delete them an reimport all.
Have you rebuild / Gradel Build the project?
I did a Project with Room as well and i had no problems having the same syntax.
in my case, i have implement #Dao annotation and still get the error. the error is :
error: Dao class must be annotated with #Dao public final class NonExistentClass{ }
just make sure your room dependencies version same as the others, my room dependencies :
kapt "androidx.room:room-compiler:2.2.0"
implementation "androidx.room:room-runtime:2.2.0"
implementation "androidx.room:room-ktx:2.2.0"
don't forget to use kapt instead of annotation processor and add :
apply plugin: 'kotlin-kapt'
above your build.gradle module app, because annotationProcessor will cause another errors, like database_impl.
then you should clean and build the project
hope it will help whoever see this
#Database(entities = {ObjInspectionSqlite.class}, version = 2, exportSchema = false)
#TypeConverters({InspeccionDateTypeConverter.class})
public abstract class DataBaseInspections extends RoomDatabase {
public static BaseDeDatosInspecciones instance;
public abstract InspectionsDao inspectionsDao();
public abstract ObjInspectionSqlite inspectionSqlite();
...
}
note that ObjInspectionSqlite is a class whit #Entity , and I've declared it abstract in my DataBase
This will trow:
"error: Dao class must be annotated with #Dao"
even if you declared your dao correctly.
Maybe you declared your class as an abstract somewhere in your database and the DB expects it to be an abstract Dao that can be implemented.
Add code snippet of your DataBase since all answers point to a coding error in that class.
Related
I dont know why but Android Studiodoesnt find my DatabaseView. Even if i install others projects
This is the DatabaseView. Its created in a class called LibroDatos.
package com.example.pruebaexamenroom;
import androidx.room.DatabaseView;
#DatabaseView(value = "SELECT libro.id, libro.titulo, libro.autor," +
"libro.idCliente,cliente.name as nombreCliente FROM libro " +
"INNER JOIN Cliente ON libro.idCliente = cliente.idHumano",
viewName = "v_LibroDatos")
public class LibroDatos {
public int id;
public String Titulo;
public String Autor;
public int idCliente;
public String nombreCliente;
}
This is the Dao. Here is where its said that doesnt exist
package com.example.pruebaexamenroom;
import androidx.lifecycle.LiveData;
import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.Query;
import androidx.room.Transaction;
import java.util.List;
#Dao
public interface DaoLibro {
#Transaction
#Query("SELECT * FROM v_LibroDatos")
List<LibroDatos> obtenerLibros();
#Insert
void InsertarLibro(Libro...libros);
#Query("UPDATE libro SET titulo =:titulo,autor=:autor WHERE id =:id")
void updateLibro(int id,String titulo,String autor);
#Query("DELETE FROM libro")
void borrarLibro();
}
This is the AppDatabase. Its all declared in here.
package com.example.pruebaexamenroom;
import androidx.room.Database;
import androidx.room.RoomDatabase;
#Database(
entities = {Libro.class, Cliente.class},
views = {LibroDatos.class},
version = 1
)
public abstract class AppDatabase extends RoomDatabase {
public abstract DaoCliente daoCliente();
public abstract DaoLibro daoLibro();
}
I believe that you can just ignore the error and that the project will compile successfully.
If while coding the obtenerLibros Query you type in v for the view you will see that it does know as it prompts to complete e.g.
but then still flags it as an error. However it compiles successfully.
Note if you look at the build log, then it has warnings:-
warning: The query returns some columns [titulo, autor] which are not used by a.a.so75347005javaroomviewnotfound.LibroDatos. You can use #ColumnInfo annotation on the fields to specify the mapping. You can annotate the method with #RewriteQueriesToDropUnusedColumns to direct Room to rewrite your query to avoid fetching unused columns.
a.a.so75347005javaroomviewnotfound.LibroDatos has some fields [Titulo, Autor] which are not returned by the query. If they are not supposed to be read from the result, you can mark them with #Ignore annotation. You can suppress this warning by annotating the method with #SuppressWarnings(RoomWarnings.CURSOR_MISMATCH). Columns returned by the query: id, titulo, autor, idCliente, nombreCliente. - a.a.so75347005javaroomviewnotfound.DaoLibro.obtenerLibros()
So you may wish to
Include the #RewriteQueriesToDropUnusedColumns annotation
Rename the member variables in the LibroDatos class to be lower case.
for 1 :-
#Transaction
#RewriteQueriesToDropUnusedColumns //<<<<<<<<<< ADDED
#Query("SELECT * FROM v_LibroDatos")
List<LibroDatos> obtenerLibros();
for 2 :-
public class LibroDatos {
public int id;
public String titulo; //<<<<<<<<<< was Titulo
public String autor; //<<<<<<<<< was Autor
public int idCliente;
public String nombreCliente;
}
I am using spring data and my DAO looks like
public interface StudentDAO extends JpaRepository<StudentEntity, Integer> {
public findAllOrderByIdAsc(); // I want to use some thing like this
}
In above code, commented line shows my intent. Can spring Data provides inbuilt functionality
to use such a method to find all records order by some column with ASC/DESC?
public interface StudentDAO extends JpaRepository<StudentEntity, Integer> {
public List<StudentEntity> findAllByOrderByIdAsc();
}
The code above should work. I'm using something similar:
public List<Pilot> findTop10ByOrderByLevelDesc();
It returns 10 rows with the highest level.
IMPORTANT:
Since I've been told that it's easy to miss the key point of this answer, here's a little clarification:
findAllByOrderByIdAsc(); // don't miss "by"
^
AFAIK, I don't think this is possible with a direct method naming query. You can however use the built in sorting mechanism, using the Sort class. The repository has a findAll(Sort) method that you can pass an instance of Sort to. For example:
import org.springframework.data.domain.Sort;
#Repository
public class StudentServiceImpl implements StudentService {
#Autowired
private StudentDAO studentDao;
#Override
public List<Student> findAll() {
return studentDao.findAll(sortByIdAsc());
}
private Sort sortByIdAsc() {
return new Sort(Sort.Direction.ASC, "id");
}
}
Simple way:
repository.findAll(Sort.by(Sort.Direction.DESC, "colName"));
Source: https://www.baeldung.com/spring-data-sorting
Please have a look at the Spring Data JPA - Reference Documentation, section 5.3. Query Methods, especially at section 5.3.2. Query Creation, in "Table 3. Supported keywords inside method names" (links as of 2019-05-03).
I think it has exactly what you need and same query as you stated should work...
Yes you can sort using query method in Spring Data.
Ex:ascending order or descending order by using the value of the id field.
Code:
public interface StudentDAO extends JpaRepository<StudentEntity, Integer> {
public findAllByOrderByIdAsc();
}
alternative solution:
#Repository
public class StudentServiceImpl implements StudentService {
#Autowired
private StudentDAO studentDao;
#Override
public List<Student> findAll() {
return studentDao.findAll(orderByIdAsc());
}
private Sort orderByIdAsc() {
return new Sort(Sort.Direction.ASC, "id")
.and(new Sort(Sort.Direction.ASC, "name"));
}
}
Spring Data Sorting: Sorting
I try in this example to show you a complete example to personalize your OrderBy sorts
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.*;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import org.springframework.data.domain.Sort;
/**
* Spring Data repository for the User entity.
*/
#SuppressWarnings("unused")
#Repository
public interface UserRepository extends JpaRepository<User, Long> {
List <User> findAllWithCustomOrderBy(Sort sort);
}
you will use this example :
A method for build dynamically a object that instance of Sort :
import org.springframework.data.domain.Sort;
public class SampleOrderBySpring{
Sort dynamicOrderBySort = createSort();
public static void main( String[] args )
{
System.out.println("default sort \"firstName\",\"name\",\"age\",\"size\" ");
Sort defaultSort = createStaticSort();
System.out.println(userRepository.findAllWithCustomOrderBy(defaultSort ));
String[] orderBySortedArray = {"name", "firstName"};
System.out.println("default sort ,\"name\",\"firstName\" ");
Sort dynamicSort = createDynamicSort(orderBySortedArray );
System.out.println(userRepository.findAllWithCustomOrderBy(dynamicSort ));
}
public Sort createDynamicSort(String[] arrayOrdre) {
return Sort.by(arrayOrdre);
}
public Sort createStaticSort() {
String[] arrayOrdre ={"firstName","name","age","size");
return Sort.by(arrayOrdre);
}
}
Combining all answers above, you can write reusable code with BaseEntity:
#Data
#NoArgsConstructor
#MappedSuperclass
public abstract class BaseEntity {
#Transient
public static final Sort SORT_BY_CREATED_AT_DESC =
Sort.by(Sort.Direction.DESC, "createdAt");
#Id
private Long id;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
#PrePersist
void prePersist() {
this.createdAt = LocalDateTime.now();
}
#PreUpdate
void preUpdate() {
this.updatedAt = LocalDateTime.now();
}
}
DAO object overloads findAll method - basically, still uses findAll()
public interface StudentDAO extends CrudRepository<StudentEntity, Long> {
Iterable<StudentEntity> findAll(Sort sort);
}
StudentEntity extends BaseEntity which contains repeatable fields (maybe you want to sort by ID, as well)
#Getter
#Setter
#FieldDefaults(level = AccessLevel.PRIVATE)
#Entity
class StudentEntity extends BaseEntity {
String firstName;
String surname;
}
Finally, the service and usage of SORT_BY_CREATED_AT_DESC which probably will be used not only in the StudentService.
#Service
class StudentService {
#Autowired
StudentDAO studentDao;
Iterable<StudentEntity> findStudents() {
return this.studentDao.findAll(SORT_BY_CREATED_AT_DESC);
}
}
I need to search in an h2 database for Company class instances that have a specific code, but I can't figure out how.
I have tried using the Finder class, but there don't seem to be any find methods in the version i am using except findbyid().
Here is the beginning of my Company class:
#Entity
public class Company extends Model {
#Id
public Integer id;
public String code;
public String name;
public String adress;
public String fiscalCode;
public String bankAccount;
public static Finder<Integer, Company> find = new Finder<>(Company.class);
Thank you!
Depending on the version of Play you are using I'd suggest to try the following:
Company.find.where().like("code", "%foo%").findList();
or
Define your finder
public class CompanyFinder extends Finder<Long,Company> {
public CompanyFinder() {
super(Company.class);
}
// Add finder methods ...
public Company byCode(String code) {
return query().eq("code", code).findOne();
}
}
Update your entity to reference this finder:
#Entity
public class Company extends BaseModel {
public static final CompanyFinder find = new CompanyFinder();
...
}
Call the finder:
Company c = Company.find.byCode("foo");
#Database(entities = {User.class}, version = 2, exportSchema = false)
public abstract class AppDatabase extends RoomDatabase {
public abstract userDao userDao();
}
Pojo user class
#Entity
public class User {
#PrimaryKey(autoGenerate = true)
private int id;
public User(){
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
Dao
#Dao
public interface userDao {
#Query("SELECT * FROM User WHERE id = :id")
Flowable<User> get(int id);
#Insert
Completable insert(User user);
}
Dependencies
implementation "androidx.room:room-runtime:2.2.3"
annotationProcessor "androidx.room:room-compiler:2.2.3"
implementation "android.arch.persistence.room:rxjava2:1.1.1"
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
implementation "io.reactivex.rxjava2:rxjava:2.2.14"
Error
error: no suitable method found for createFlowable(RoomDatabase,boolean,String[],<anonymous Callable<User>>)
method RxRoom.createFlowable(RoomDatabase,String...) is not applicable
(varargs mismatch; boolean cannot be converted to String)
method RxRoom.<T>createFlowable(RoomDatabase,String[],Callable<T>) is not applicable
(cannot infer type-variable(s) T
(actual and formal argument lists differ in length))
where T is a type-variable:
T extends Object declared in method <T>createFlowable(RoomDatabase,String[],Callable<T>)
I'm trying to figure out how to work with rxjava in the room, I follow the examples, but it throws an error, what is the problem? Completable works fine
I have no idea why you marked ianhanniballake's answer as a correct one.
Dependency "androidx.room:room-ktx:2.2.3" has nothing to do with RxJava.
I my case I fixed the problem by adding this dependency
implementation "androidx.room:room-rxjava2:2.2.3"
insted of my old one:
implementation 'android.arch.persistence.room:rxjava2:1.1.1'
hope this will help
As per the Room Declaring Dependencies documentation, you need a dependency on room-ktx to use Coroutines and, with that, Flowable:
implementation "androidx.room:room-ktx:2.2.3"
I am using spring data and my DAO looks like
public interface StudentDAO extends JpaRepository<StudentEntity, Integer> {
public findAllOrderByIdAsc(); // I want to use some thing like this
}
In above code, commented line shows my intent. Can spring Data provides inbuilt functionality
to use such a method to find all records order by some column with ASC/DESC?
public interface StudentDAO extends JpaRepository<StudentEntity, Integer> {
public List<StudentEntity> findAllByOrderByIdAsc();
}
The code above should work. I'm using something similar:
public List<Pilot> findTop10ByOrderByLevelDesc();
It returns 10 rows with the highest level.
IMPORTANT:
Since I've been told that it's easy to miss the key point of this answer, here's a little clarification:
findAllByOrderByIdAsc(); // don't miss "by"
^
AFAIK, I don't think this is possible with a direct method naming query. You can however use the built in sorting mechanism, using the Sort class. The repository has a findAll(Sort) method that you can pass an instance of Sort to. For example:
import org.springframework.data.domain.Sort;
#Repository
public class StudentServiceImpl implements StudentService {
#Autowired
private StudentDAO studentDao;
#Override
public List<Student> findAll() {
return studentDao.findAll(sortByIdAsc());
}
private Sort sortByIdAsc() {
return new Sort(Sort.Direction.ASC, "id");
}
}
Simple way:
repository.findAll(Sort.by(Sort.Direction.DESC, "colName"));
Source: https://www.baeldung.com/spring-data-sorting
Please have a look at the Spring Data JPA - Reference Documentation, section 5.3. Query Methods, especially at section 5.3.2. Query Creation, in "Table 3. Supported keywords inside method names" (links as of 2019-05-03).
I think it has exactly what you need and same query as you stated should work...
Yes you can sort using query method in Spring Data.
Ex:ascending order or descending order by using the value of the id field.
Code:
public interface StudentDAO extends JpaRepository<StudentEntity, Integer> {
public findAllByOrderByIdAsc();
}
alternative solution:
#Repository
public class StudentServiceImpl implements StudentService {
#Autowired
private StudentDAO studentDao;
#Override
public List<Student> findAll() {
return studentDao.findAll(orderByIdAsc());
}
private Sort orderByIdAsc() {
return new Sort(Sort.Direction.ASC, "id")
.and(new Sort(Sort.Direction.ASC, "name"));
}
}
Spring Data Sorting: Sorting
I try in this example to show you a complete example to personalize your OrderBy sorts
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.*;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import org.springframework.data.domain.Sort;
/**
* Spring Data repository for the User entity.
*/
#SuppressWarnings("unused")
#Repository
public interface UserRepository extends JpaRepository<User, Long> {
List <User> findAllWithCustomOrderBy(Sort sort);
}
you will use this example :
A method for build dynamically a object that instance of Sort :
import org.springframework.data.domain.Sort;
public class SampleOrderBySpring{
Sort dynamicOrderBySort = createSort();
public static void main( String[] args )
{
System.out.println("default sort \"firstName\",\"name\",\"age\",\"size\" ");
Sort defaultSort = createStaticSort();
System.out.println(userRepository.findAllWithCustomOrderBy(defaultSort ));
String[] orderBySortedArray = {"name", "firstName"};
System.out.println("default sort ,\"name\",\"firstName\" ");
Sort dynamicSort = createDynamicSort(orderBySortedArray );
System.out.println(userRepository.findAllWithCustomOrderBy(dynamicSort ));
}
public Sort createDynamicSort(String[] arrayOrdre) {
return Sort.by(arrayOrdre);
}
public Sort createStaticSort() {
String[] arrayOrdre ={"firstName","name","age","size");
return Sort.by(arrayOrdre);
}
}
Combining all answers above, you can write reusable code with BaseEntity:
#Data
#NoArgsConstructor
#MappedSuperclass
public abstract class BaseEntity {
#Transient
public static final Sort SORT_BY_CREATED_AT_DESC =
Sort.by(Sort.Direction.DESC, "createdAt");
#Id
private Long id;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
#PrePersist
void prePersist() {
this.createdAt = LocalDateTime.now();
}
#PreUpdate
void preUpdate() {
this.updatedAt = LocalDateTime.now();
}
}
DAO object overloads findAll method - basically, still uses findAll()
public interface StudentDAO extends CrudRepository<StudentEntity, Long> {
Iterable<StudentEntity> findAll(Sort sort);
}
StudentEntity extends BaseEntity which contains repeatable fields (maybe you want to sort by ID, as well)
#Getter
#Setter
#FieldDefaults(level = AccessLevel.PRIVATE)
#Entity
class StudentEntity extends BaseEntity {
String firstName;
String surname;
}
Finally, the service and usage of SORT_BY_CREATED_AT_DESC which probably will be used not only in the StudentService.
#Service
class StudentService {
#Autowired
StudentDAO studentDao;
Iterable<StudentEntity> findStudents() {
return this.studentDao.findAll(SORT_BY_CREATED_AT_DESC);
}
}