Error using sql statement in Android Room:SQL error or missing database (no such column:xx) - android-room

I used the following statement in mysql to query the data successfully:
"SELECT * FROM (SELECT * FROM `im_msg_hist` ORDER BY dTime DESC) AS T where toId='xxxx' or frmId='xxxx' GROUP BY toId".
but when i using such a statement in Android Room gives an error:"There is a problem with the query: [SQLITE_ERROR] SQL error or missing database (no such column: tb_msg.id)"
this is Entity :
#Entity(tableName = "tb_msg")
public class Message {
#PrimaryKey(autoGenerate = true)
#ColumnInfo(name = "id")
private long id;
#ColumnInfo(name = "send_id")
private String sendId;
#ColumnInfo(name = "receive_id")
private String receiveId;
...
}
this is dao:
#Dao
public interface MessageDao {
#Query("SELECT * FROM (SELECT * FROM tb_msg ORDER BY time DESC) AS T WHERE send_id=:userId or receive_id=:userId GROUP BY send_id")
LiveData<List<PersonalMsg>> getGroupByReceiveId(String userId);
}

You should clarify table name columns name for room. I suggest you to refer this doc
Entity(tableName = "tb_msg")
public class Message {
#PrimaryKey
#ColumnInfo(name = "id")
private long id;
#ColumnInfo(name = "send_id")
private String sendId;
#ColumnInfo(name = "receive_id")
private String receiveId;
...
}

Related

JPA Native Query. Cannot select specific columns

I'm working on a Spring Boot project using JPA to connect to my DB. I wan to make a native query to select some specific fields but it doesn't allow me to do. For example, I want to get only id, firstName, lastName and phoneNumber of a customer But it will throws me error like,
The column name current_access_token was not found in this ResultSet.
Here is my query code in the JPA repository,
#Query(value = "SELECT c.id, c.phone_number, c.firstname, c.lastname FROM tbl_customers c JOIN tbl_subscriptions s ON c.id = s.customer_id WHERE s.role = 'member' AND s.deleted_at IS NULL", nativeQuery = true)
List<Customer> findMemberByRole(String role);
Here is my Cutomer.java
#Getter
#Setter
#Accessors(chain=true)
#NoArgsConstructor
#AllArgsConstructor
#ToString
#Entity
#Table(name = "tbl_customers")
public class Customer implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(unique = true)
private Long id;
#Column(nullable = false, name = "phone_number")
private String phoneNumber;
private String firstname;
private String lastname;
#Column(name = "current_access_token")
private String currentAccessToken;
#Column(name = "consent_accepted")
private Boolean consentAccepted;
...
...
}
How can I avoid or ignore unwanted columns? Thanks a lot for helps.
If you really want to return only 4 columns from the customer table, then the signature you want to use here is List<Object[]>:
#Query(value = "SELECT c.id, c.phone_number, c.firstname, c.lastname FROM tbl_customers c JOIN tbl_subscriptions s ON c.id = s.customer_id WHERE s.role = 'member' AND s.deleted_at IS NULL", nativeQuery = true)
List<Object[]> findMemberByRole(String role);
Then, when accessing your result set, you would use something like:
List<Object[]> resultSet = findMemberByRole("admin");
for (Object[] rs : resultSet) {
Long id = (Long) rs[0];
String phoneNumber = (String) rs[1];
String firstName = (String) rs[2];
String lastName = (String) rs[3];
}

Spring boot JPA - Insert or update a list of entities

I have a repo with a unique constraint on 2 fields, connection_id and token_type:
#Entity
#Table(
name = "business_api_token",
schema = "public",
uniqueConstraints = {
#UniqueConstraint(
name = "business_api_token_unique_connection_id_and_token_type",
columnNames = {"connection_id", "token_type"}
)
}
)
public class BusinessApiToken {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#OneToOne
#JoinColumn(
name = "connection_id",
nullable = false,
foreignKey = #ForeignKey(
name = "fk_business_api_token_connection_id"
)
)
private AccountingConnection connection;
#Column(name = "token_type")
#Enumerated(EnumType.STRING)
private ApiTokenType tokenType;
#Column(name = "token_value")
private String tokenValue;
...
}
I saw some posts saying add a custom query, something like this:
#Modifying
#Query("update User u set u.firstname = ?1, u.lastname = ?2 where u.id = ?3")
void setUserInfoById(String firstname, String lastname, Integer userId);
But how would I do this for a list? I was doing this:
businessApiTokenRepository.saveAll(tokens)
Which gives an error.
The tokens are created elsewhere without knowledge of existing ones, I can do another query to check first but that seems inefficient, and I have to do this all over.
Thanks

Spring Data lock table to read while writing

I am using Spring data in my app (2.0.1). The app is REST-based service which add orders.
The order entity looks as follows:
#Entity
#Table(name = "orders")
#Data
#NoArgsConstructor
public class OrderEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Version
private int version;
private Date date;
private String post;
private BigDecimal totalAmount;
#Enumerated(EnumType.STRING)
private OrderStatus status;
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinColumn(name = "order_id")
List<OrderSetEntity> sets;
private int dailyNumber;
private String documentNumber;
The posting or orders happens in OrderService:
public Long postOrder(OrderDTO orderDTO){
Date date = new Date();
OrderEntity order = new OrderEntity(date, orderDTO.getPost(), orderDTO.getPaymentMethod());
Integer dailyNumber = orderRepository.findDailyNumberByDate(date) + 1;
order.setDailyNumber(dailyNumber);
orderRepository.save(order);
return order.getId();
}
while findDailyNumberByDate is implemented this way:
#Override
public int findDailyNumberByDate(Date date) {
String sql = String.format("select max(o.dailyNumber) from OrderEntity o ");
Query query = entityManager.createQuery(sql);
Integer result = (Integer) query.getSingleResult();
if (result == null){
return 0;
}else {
return result.intValue();
}
Now I have a problem, that it get duplicated dailyNumber. The table isn't locked for reading when I am about to write into it.
How can I achieve it?
I tried lockin the table - #Lock(LockModeType.PESSIMISTIC_WRITE)
or query.setLockMode(LockModeType.PESSIMISTIC_FORCE_INCREMENT);
but is still isn't working.
Thanks a lot for help
LockModeType can work in different ways with different databases, especially with Oracle db it gets a little tricky. A similar issue was answered here jpa lockmode type npt working as expected

Mapping objects from Room Persistence

I have classes - Subject.java
#Entity(tableName = Constants.SUBJECT_ENTITY)
public class Subject {
#PrimaryKey
private int id;
#ColumnInfo(name = "name")
private String name;
...
}
Grade.java
#Entity(tableName = Constants.GRADE_ENTITY,
foreignKeys = #ForeignKey(
entity = Subject.class,
onDelete = CASCADE,
parentColumns = "id",
childColumns = "subjectId"))
public class Grade implements Serializable {
#PrimaryKey
private int id;
#ColumnInfo(name = "semester")
private int semester;
#ColumnInfo(name = "subjectId")
private int subjectId;
...
}
SubjectAndAllGrades.java
public class SubjectAndAllGrades {
public int id;
public String name;
#Relation(parentColumn = "id", entityColumn = "subjectId")
public List<Grade> oceny;
...
}
I have performed some query in my SubjectDAO
#Query("SELECT distinct s.id as id, s.name as name " +
"FROM subject s, grade g " +
"WHERE s.id = g.subjectId " +
"AND g.semester = :semester ")
Flowable<List<SubjectAndAllGrades>> getSubjectAndAllItsGradesForSemester(int semester);
In this query as you can probably guess Im trying to select all Subjects with its grades with specific semester. However results of this query return list of SubjectAndAllGrades objects connected by subjectId key, but with no respect to the condition
g.semester = :semester
How could I achive this query?

HQL query for Association

I am having below tables here but having some problem while fetching results.
#Entity
#Table(name = "USER_VW")
public class WorkspaceUserImpl
{
#JoinColumn(name = "USER_ID", insertable=false, updatable=false)
#OneToOne(targetEntity = UserImpl.class, fetch = FetchType.EAGER)
private User user;
}
#Table(name = "IK_USER")
#Inheritance(strategy = InheritanceType.JOINED)
#AttributeOverride(name = "id", column = #Column(name = "USER_ID") )
public class UserImpl extends BaseAuditable<UserIdentifier>implements User, UserAuthentication {
private static Logger log = LoggerFactory.getLogger(UserImpl.class);
#Id
#Type(type = "com.commons.UserIdentifierTypeMapper")
#Column(name = "USER_ID")
private UserIdentifier id;
}
and User
Public Inteface User
{
UserIdentifier getId();
}
Now i have written an HQL query to fetch all the data from WorkspaceUserImpl class with a given user ID for UserImpl class like below.
SELECT w from WorkspaceUserImpl w where w.user.id = : user_id;
and also tried
SELECT w from WorkspaceUserImpl as w INNER JOIN w.user as u where u.id = : user_id;
and even tried with JOIN FETCH also
and setting the parameter user_id with some say 1234.
but am getting List as emply for the partcular ID but in DB its having 5 records.
am i making any query mistake here? kindly advice..
Have you tried below query:
from WorkspaceUserImpl as w JOIN FETCH w.user as u where u.id = : user_id;

Resources