Flowable in room - java

#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"

Related

spring-data-jdbc deleteBy<field> method return extraordinary result type

I try declare and use deleteBy method with spring-data-jdbc repositories like this
public interface TokenRepository extends CrudRepository<OpToken, Long> {
void deleteByBreed(Long breed);
}
When i tried to call method
private TokenRepository tokenRepository;
...
...
tokenRepository.deleteByBreed(123L);
I got exception: MethodNotFoundException:
java.lang.NoSuchMethodException: void.()
I decided, that delete method should return number of rows it processed. So, i rewrite my repository interface like this
public interface TokenRepository extends CrudRepository<OpToken, Long> {
long deleteByBreed(Long breed);
}
But now i have got another exception:
org.springframework.jdbc.IncorrectResultSetColumnCountException: Incorrect column count: expected 1, actual 4
It's looks like method return entity or list of entities it try to delete. But i do not need them.
How can i declare this method in my case?
By Entity looks like this:
#Data
public class OpToken implements Persistable<Long> {
#Transient
private boolean newEntity;
#Id
#Column("jti")
private Long jti;
#Column("breed")
private Long breed;
#Column("id_account")
private Long idAccount;
#Column("exp")
private Date exp;
#Override
public Long getId() {
return jti;
}
#Override
public boolean isNew() {
return newEntity;
}
}
With the current version derived delete queries aren't supported yet. Watch https://github.com/spring-projects/spring-data-jdbc/issues/771 to get notified when this changes.
The solution provided by #MadMax is correct: used a dedicated query:
#Modifying
#Query("delete from account.op_token t where t.breed = :breed")
void deleteByBreed(#Param("breed") Long breed);
It's only one worked
#Modifying
#Query("delete from account.op_token t where t.breed = :breed")
Long(or void) deleteByBreed(#Param("breed") Long breed);
But the query only works as long as your entity has no value objects (which are not #Embedded). I had a Customer entity with value objects and so I used this method in my service (customerId is unique):
#Transactional
public void deleteByCustomerId(final String customerId) {
customerRepository.findByCustomerId(customerId).ifPresent(customerRepository:delete);
}

CustomRepository clashes with <S>save(S) in org.springframework.data.repository.CrudRepository return type java.lang.Long is not compatible with S

I am trying to save a record in DB, which in return should return me the primary key.
here is my Entity Class:
#Entity
public class CustomEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
private Integer eventTypeId;
//getter setter here
}
Here goes my repository:
public interface CustomRepository extends JpaRepository<CustomEntity, Long> {
Long save(customRepository);
}
When i try to call the repository interface in my Service class, I get this Exception at compile time:
Error:(32, 8) java: save(model.CustomEntity) in repository.CustomRepository clashes with <S>save(S)
in org.springframework.data.repository.CrudRepository return type java.lang.Long is not compatible with S
I understand JPA Repository extends PaginationAndSorting which in returns extends CrudRepository, how do i resolve this issue.
the methods signature is
<S extends T> S save(S entity)
so you need to return the same Type as you pass as parameter. In your case CustomEntity.
The parameter's type and return value should be the same.
try to change your code:
public interface CustomRepository extends JpaRepository<CustomEntity, Long> {
CustomEntity save(customRepository);
}
and then get id value from CustomEntity object for example:
public void someMethod(){
CustomEntity entity = repo.save(new CustomEntity());
Long savedId = entity.getId();
}

Spring Data JPA mapping nested entities

I'm a little bit confused about using projections in Spring Data JPA.
I wanted to optimize my queries by requesting only needed columns (preferably) in one query, and I thought that using projections is a good idea. But it seems that projection with nested projection becomes open and requests all columns and further nesting is impossible.
I've tried to find a solution with #Query (cannot find how to map nested lists), #EntityGraph (cannot find how to request only specified column) and #SqlResultSetMapping (cannot find how to make mapping nested lists), but it hasn't worked for me.
Is there any solution except receiving List<Object[]> and manually mapping?
I have the next entities classes (simplified for the question):
public class TestAttempt{
private Long id;
private User targetUser;
private Test test;
}
public class Test{
private Long id;
private String name;
private Set<Question> questions;
}
public class Question{
private Long id;
private String name;
private Test test;
}
And I wanted to write something like this (it can be just TestAttempt with null in unused fields):
public interface TestAttemptList {
Long getId();
Test getTest();
interface Test {
String getName();
List<Question> getQuestions();
interface Question {
String getName();
}
}
}
public interface TestAttemptRepository extends JpaRepository<TestAttempt, Long> {
List<TestAttemptList> getAllByTargetUserId(Long targetUserId);
}
And in result get something like this:
{
id: 1,
test: {
name: test1,
questions: [{
name: quest1
}, {
name: quest2
}]
}
}
Ive done something like this... You'll have your repository interfaces which will extend CrudRepository et. al. with the full objects (TestAttempt etc) You define your projections separately. The projection interfaces can contain other projection interfaces (TestAttemptSummary can contain a TestSummary) When the projection interface is used within the given repository the defined methods are applied to the object type the repository is configured for. Something like this.
public interface TestAttemptSummary {
Long getId();
TestSummary getTest();
}
public interface TestSummary {
String getName();
List<QuestionSummary> getQuestions();
}
public interface QuestionSummary {
String getName();
}
public interface TestAttemptRepository extends CrudRepository<TestAttempt, Long> {
TestAttemptSummary getTestAttemptSummary();
}

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.

Create a class that can handle all type of CRUD Operation. No need to make SessionFactory or Session Object Each Time I need to do CRUD

I want to make a class in java have a method that can interact with Hibernate configuration and do certain operation is identified as ENUM (eg: read, update, add, delete and etc.)
Method Parameters should be (Enum operations, class DTO, NamedQuery namedquery ,DTOObject Object_to_persist, param(any extra argument)).
Method should be as convenient that i can call it whenever i need by Passing actual argument(Operation.read, USERDTO.class , namedquery , USERDTO obj_UserDTO , HashMap hmapData).
/* Enum Defined Operation done to the database.
*/
public enum Operations {READ,UPDATE,ADD,DELETE};
/*Centralized Method Defination for Basic CRUD Operation */
public T<?> DatabaseCRUDOperations((Operation.READ,USERDTO.class , namedquery , USERDTO obj_UserDTO , HashMap<String, String> hmapid){
switch(Operation opts){
case Operation.Read : //Call Read Method
break;
case Operation.UPDATE: //call Update Method
break;
......
......
default://call any Error Method or set error
}
}
Basically i want to define a custom Class (one kind of internal Framework for project) which have all basic CRUD Operation should done via this Class only. No need to create SessionFactory or Session Object Create every Where i Need.
Please Suggest by some code-snipt.
Java Generics to the rescue! Prepare to be amazed.
Your abstract entity (useful if you want to define methods to use in things like, for example, generic controller classes):
public abstract class AbstractEntity<ID extends Serializable> implements Serializable {
public abstract ID getPrimaryKey();//I simply put this here as an example
}
Create the generic DAO interface:
public interface IGenericDAO<T extends AbstractEntity<ID>, ID extends Serializable> {
T findByPrimaryKey(ID id);
T save(T entity);
void delete(T entity);
List<T> saveAll(List<T> entities);
.
.
.
}
Then, define your abstract generic DAO:
public abstract class AbstractHibernateDAO<T extends AbstractEntity<ID>, ID extends Serializable> implements IGenericDAO<T, ID> {
protected Class<T> persistentClass;
protected AbstractHibernateDAO(){}
#SuppressWarnings({ "unchecked", "rawtypes" })
public AbstractHibernateDAO(Class c) {
persistentClass = c;
}
#Override
#SuppressWarnings("unchecked")
public T findByPrimaryKey(ID id){
return (T) HibernateUtil.getSession().get(persistentClass, id);
}
#Override
public T save(T entity){
HibernateUtil.getSession().saveOrUpdate(entity);
return entity;
}
#Override
public List<T> saveAll(List<T> entities){
for(int i = 0; i < entities.size(); i++){
HibernateUtil.getSession().saveOrUpdate(entities.get(i));
}
return entities;
}
#Override
public void delete(T entity){
HibernateUtil.getSession().delete(entity);
}
.
.
.
}
DAO interface for entity (For this example, I'm using Integer as the primary key):
public interface IMyEntityDAO extends IGenericDAO<MyEntity, Integer> {
}
Now (drum roll), you are ready to lay some concrete (classes)...
DAO:
public class MyEntityDAO extends AbstractHibernateDAO<MyEntity, Integer> implements IMyEntityDAO {
public MyEntityDAO() {
super(MyEntity.class);
}
}
MyEntity:
#Entity
#Table(name = "my_entity_table")
public class MyEntity extends AbstractEntity<Integer>{
#Id
#Column(name = "index")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
public Integer getPrimaryKey (){
return id;
}
.
.
.
}
Boom. (Mic drop)
Let me know if you need further explanation!
I can't rightfully post this without giving credit to Cameron McKenzie and his amazing book here . Which opened my eyes to a whole new world realizing the power of generics.

Categories

Resources