Why my Databaseview name appears as non found in my Dao? - java

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;
}

Related

Realm java search Sub model?

Really hard to Google this one as I am not entirely sure what it's called.
In my android application I have some Models to return some data from Realm.
Example structure:
Shipment.java :
import java.io.Serializable;
import io.realm.RealmList;
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
public class Shipment extends RealmObject implements Serializable {
#PrimaryKey
public int id;
public Technician technician;
Technician.java :
import io.realm.RealmList;
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
public class Technician extends RealmObject {
#PrimaryKey
public int id;
So I am trying to return the shipments that correspond to a technician id.
In my ShipmentsService.java I have this:
public RealmResults<Shipment> forTechnician()
{
Realm realm = Realm.getDefaultInstance();
return realm.where(Shipment.class).contains("technician", "11");
}
Now I know that won't work but I am not sure how I can query based on this relationship.
Link queries. Also, Realm.getDefaultInstance() increments a ref count, so you probably shouldn't let it dangle there like that.
public RealmResults<Shipment> forTechnician(Realm realm) {
return realm.where(Shipment.class).equalTo("technician.id", 11);
}
You can do query like this :
public RealmResults<Shipment> forTechnician()
{
Realm realm = Realm.getDefaultInstance();
return realm.where(Shipment.class).equalTo("technician.id", 11).findAll();
}

Android Room error: Dao class must be annotated with #Dao

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.

JPA and Java SE - Table not created for Entity class, due to additional convenience methods

I am currently writing a Netbeans platform application for persistence I use JPA 2.1 and eclipse link as provider. I have the following entity class:
import java.util.UUID;
import javafx.beans.property.SimpleStringProperty;
import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Transient;
/**
*
* #author forell
*/
#Entity
#Access(AccessType.FIELD)
public class MaterialAbc {
#Id
private String id;
//... several additional fields, that all work fine
private String substanceInstances = "";
public MaterialAbc(){
id = UUID.randomUUID().toString();
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
//.. getters and setters for the omitted fields
public String getSubstanceInstances() {
return substanceInstances;
}
public void setSubstanceInstances(String substanceInstances) {
this.substanceInstances = substanceInstances;
}
/* IF I UNCOMMENT THESE LINES THE DATATABLE IS NOT CREATED ANYMORE
IS THERE A WAY TO SOLVE THIS?
public List<SubstanceInstance2> getSubs() {
List<SubstanceInstance2> subs = new ArrayList<>();
if (!"".equals(substanceInstances)){
List<String> values = Arrays.asList(substanceInstances.split("|"));
values.forEach(value->{
subs.add(SubstanceInstance2.unSerialize(value));
});
}
return subs;
}
public void setSubs(List<SubstanceInstance2> subs) {
substanceInstances = "";
subs.forEach(sub->{
substanceInstances =substanceInstances + sub.serialize() + "|";
});
substanceInstances = substanceInstances.substring(0, substanceInstances.length()-1);
}
*/
As is the class works fine, as soon as I uncomment the two methods at the bottom that "unserialize" an object that is nested in the string substanceInstances, eclipselink is not creating the datatables anymore. Is there a way to solve this, or do need to add an extra layer.
In the meantime I actually found a solution to the problem. It seems eclipselink does not convert the Entity-bean into a table, if there are lambda expressions used in the methods. In the end I converted
values.forEach(value->{
subs.add(SubstanceInstance2.unSerialize(value));
});
into
for (String value:values){
subs.add(SubstanceInstance2.unSerialize(value));
}
And everthing works nicely. As to the reason why, no idea!

session.get() unable to resolve field,argument

I'm totally new to Spring MVC but still trying to understand its methods and its way of referencing things. There's a video tutorial course I'm following.
I'm trying to implement a Model through a class.
ProductDaoImpl.java
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import java.util.List;
#Repository
public class ProductDaoImpl implements ProductDao {
#Autowired
private SessionFactory sessionFactory;
#Override
public void addProduct(Product product) {
Session session = sessionFactory.getCurrentSession();
session.saveOrUpdate(product);
session.flush();
}
#Override
public Product getProductById(String id) {
Session session = sessionFactory.getCurrentSession();
Product product = (Product) session.get(Product.class.productId);
// unable to resolve the productId on get()
return product;
}
#Override
public List<Product> getAllProducts() {
return null;
}
#Override
public void deleteProduct(String id) {
}
}
ProductDao.java
import java.util.List;
public interface ProductDao {
void addProduct(Product product);
Product getProductById(String id);
List<Product> getAllProducts();
void deleteProduct(String id);
}
Product.java Model
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Entity
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.AUTO) //tells the system that when an instance is put to database, it will be numbered automatically starting from 1
private String productName;
private String productCategory;
private String productDescription;
private double productPrice;
private String productDimension;
private String productStatus;
private int unitInStock;
private String productManufacturer;
private String productId;
}
However, it's unable to resolve the productId argument in
#Override
public Product getProductById(String id) {
Session session = sessionFactory.getCurrentSession();
Product product = (Product) session.get(Product.class.productId);
return product;
}
Is get() method able to access the fields of Product.class?
Is it asking for a field in Product.class.fieldHere?
I don't understand why it can't resolve the productId
I hope you can help.
Thanks.
The expression Product.class.productId doesn't make sense in Java. Product.class is a class literal, meaning that it's a constant value that represents the Product class, an instance of java.lang.Class. Class has no productId field.
Additionally, you should read the Javadoc for the method--it takes two parameters, a Class object (to tell it what sort of thing you're getting) and an ID. Your call should therefore be session.get(Product.class, id), and if you're using Hibernate 5, you don't need to cast to a Product.
All of this is rather moot, however--instead of hand-rolling a DAO targeting Hibernate, use JPA (which provides advantages such as a generic API, eliminating the need for casting) and Spring Data (which will autogenerate this entire DAO for you from nothing but an empty interface declaration). Additionally, you're dealing with topics that can get complicated, and you would do well to go through some exercises to learn core Java before tackling something like ORM.
session.get(Product.class.productId);
That's not valid Java code. get() expects two arguments: the entity class, and the ID of the entity to get. Arguments in Java are separated by a comma.
session.get(Product.class, productId);
But your variable isn't even named productId. It's named id. So the code should be
session.get(Product.class, id);
This is beginner Java stuff. I strongly suggest you practice with simpler Java exercises before using Spring and Hibernate, which are complex stuff.
session.get accepts two parameters, one is the class of your entity and the other one is the identifier
Product product = (Product) session.get(Product.class,id);

Generics and the Play Framework

I am using the Play Framework in it's current version and my model classes extend play.db.jpa.JPABase.
Today I tried to make an often used type of query generic and define a static helper method to construct it.
I wrote the following:
import play.db.jpa.Model;
import play.libs.F;
public class GenericQueries {
public static <T extends Model> F.Option<T> firstOption(
Class<T> clazz,
String query,
Object... parameters){
final T queryResult = T.find(query,parameters).first();
return (queryResult == null) ?
F.Option.<T>None() :
F.Option.Some(queryResult);
}
}
However, I get the following error:
Execution exception
UnsupportedOperationException occured : Please annotate your JPA model with #javax.persistence.Entity annotation.
I debugged into the method, at runtime T seems to be correctly set to it's corresponding Model class. I even see the annotation.
I suspect some class enhancing voodoo by the play guys responsible for this, but I am not entirely sure.
Any ideas?
Update: added Model class as Requested
Here is a shortened Version of one of the Model classes I use.
package models;
import org.apache.commons.lang.builder.ToStringBuilder;
import play.data.validation.Required;
import play.db.jpa.Model;
import play.modules.search.Field;
import play.modules.search.Indexed;
import javax.persistence.Column;
import javax.persistence.Entity;
import java.util.Date;
#Entity #Indexed
public class FooUser extends Model {
#Required
public Date firstLogin;
#Field
#Required(message = "needs a username")
#Column(unique = false,updatable = true)
public String name;
#Field
public String description;
#Required
public boolean isAdmin;
#Override
public String toString(){
return new ToStringBuilder(this)
.append("name", name)
.append("admin", isAdmin)
.toString();
}
}
In Play entites should extend play.db.jpa.Model and use #Entity annotation (class level).
For what you say I understand that you are extending play.db.jpa.JPABase.
This may be the reason of the issue, as Play (as you point) dynamically enhances classes and it may be clashing with your inheritance.
EDIT: I tested the issue
The problem is that Play is not enhancing the object T. This means that the find method called id the one of GenericModel (parent of Model) whose implementation is to throw an exception with the message.
The enhancer seems to detect only the classes with #Entity.
Even the solution of mericano1 doesn't work, the enhancer doesn't pick it. So I feel you won't be able to use that method in Play.
The best way to do that is to use a base class that extends play.db.jpa.Model with just the static methods that will be shared by the subclasses.
Add the #Entity annotation to the base class and no class fields.
import play.db.jpa.Model;
import play.libs.F;
public class BaseModel extends Model {
public static <T extends Model> F.Option<T> firstOption(
Class<T> clazz,
String query,
Object... parameters){
final T queryResult = T.find(query,parameters).first();
return (queryResult == null) ?
F.Option.<T>None() :
F.Option.Some(queryResult);
}
}
And then
#Entity
public class FooUser extends BaseModel {
....
}

Categories

Resources