Partial Entity Binding for Android Room - android-room

Would like to confirm is it possible to bind an entity bean to partial columns of a table?
Example:
Table "A" has column id, col1, col2, col3, col4, col5, ... , col10
But I only need id, col1, col2, so I create a entity bean with fields id, col1, col2 and do binding for these fields only? I tried doing this but got:
Caused by: java.lang.IllegalStateException: Room cannot verify the data integrity. Looks like you've changed schema but forgot to update the version number. You can simply fix this by increasing the version number.
Appreciate if anyone can verify is it possible to do the above binding using Room Persistence Library.
(Note: Why are there columns in my table which are not used in the mobile app. These tables schema are an exact copy of some tables in server side, hence some fields are used at server side webapp)

Returning subsets of columns
Most of the time, you need to get only a
few fields of an entity. For example, your UI might display just a
user's first name and last name, rather than every detail about the
user. By fetching only the columns that appear in your app's UI, you
save valuable resources, and your query completes more quickly.
https://developer.android.com/topic/libraries/architecture/room.html
You can define a model which does not have an #Entity annotation and use it at your select query.
// No #Entity annotation here !!!
public class NameTuple {
#ColumnInfo(name="first_name")
public String firstName;
#ColumnInfo(name="last_name")
public String lastName;
}
It isnt necessary to write another DAO (as the new class isnt an entity) - you can use the new Class as the return datatype from within any existing DAO.
// inside any existing DAO
#Query("SELECT first_name, last_name FROM user")
public List<NameTuple> loadFullName();

Related

Cassandra + SpringBoot: Configure Table to automatically add INSERT timestamp

Small question regarding Cassandra, with the context of a SpringBoot application please.
I am interested in adding onto the table the timestamp of when a row gets inserted onto the table.
Therefore, when creating the table, I do this:
create table mytable (someprimarykey text PRIMARY KEY, timestamp long, someotherfield text);
I can see a column timestamp, happy.
Then, the web application:
#Table
public class MyTable {
#PrimaryKey
private final String somePrimaryKey;
private final long timestamp;
private final String someOtherField;
//constructor + getters + setters
And when I insert, I will do the usual:
MyTable myTable = new MyTable(somePK, System.currentTimeMillis(), "foo");
myTableRepository.save(myTable);
This works fine, I can see in the table my record, with the time of the insert, happy.
Problem:
Now, for the hundreds of POJOs I am interested to insert into Cassandra, all of them are carrying this timestamp long field. Somehow, on the web application layer, I am dealing with a database concept, the timestamp of the write.
Question:
May I ask if it is possible to delegate this back to the database? Some kind of:
create table mytable (someprimarykey text PRIMARY KEY, hey-cassandra-please-automatically-add-the-time-when-this-row-is-written long, someotherfield text);
or
create table mytable (someprimarykey text PRIMARY KEY, someotherfield text WITH default timestamp-insert-time-column);
And the web app can have the abstraction creating and inserting POJOs without carrying this timestamp field?
Thank you
It isn't necessary to store the insert time of each row separately since Cassandra already stores this for all writes in the metadata.
There is a built-in CQL function WRITETIME() which returns the date/time (encoded in microseconds) when a column was written to the database.
In your case, you can query your table with:
SELECT WRITETIME(someotherfield) FROM mytable WHERE someprimarykey = ?
For details, see the CQL doc on retrieving the write time. Cheers!

Hibernate - How to get single value from another table without primary/Foreign key relationship?

I have 2 tables(Employee & Department).
Employee(ID, employee name, dept id, employee address) --> ID primary key
Department(ID, department name, address) --> ID primary key
Note: Consider no primary key / foreign key relationship between these 2 tables
Now based on dept id in Employee, i need to fetch its corresponding dept name from Department & display it in Employee.
Employee(ID, employee name, dept id(Display dept name instead of dept id, query department table to get dept name through passing dept id), employee address)
What are all possible ways to achieve this?
Regards
Raj
I see at least three possible solutions:
Create a "normal" SQL query for this, joins can be perfectly done without a PK/FK-relationship.
Perform two SQL queries: One query for fetching the employee, then extract the ID and then a second query to fetch the department by ID.
Change your JPA entities to include the relationship as you would normally do having a #OneToMany relationship so you can load the employee with its department as usual. Same as 1 applies, joins (whether done by you or by the JPA provider) don't need a PK/FK-relationship.
Whilst 1 can be done with plain SQL, 2 can be done using the entity manager without the need to write "plain" SQL. 3 would be the easiest solution, obviously.
You can #Query in repository and write your JPA query using JOIN.
Sample Query:
#Query( value = "select new map(employee.name as empName, employee.id as id, department.id as depId, department.name as depName) from Employee employee INNER JOIN Department department ON employee.depId = department.id where employee.id = :id" )
public Map<String,Object> getEmployeeById(long id);

How to UPDATE multiple rows, based on multiple conditions?

I'm trying to update a single column in a table for many rows, but each row will have a different updated date value based on a unique where condition of two other columns. I'm reading the data from a csv, and simply updating the date column in the row located from the combination of values in the other two columns.
I've seen this
SQL update multiple rows based on multiple where conditions
but the SET value will not be static, and will need to match each row where the other two column values are true. This is because in my table, the combination of those two other columns are always unique.
Psuedocode
UPDATE mytable SET date = (many different date values)
WHERE col_1 = x and col_2 = y
col_1 and col_2 values will change for every row in the csv, as the combination of these two values are unique. I was looking into using CASE in postgres, but I understand it cannot be used with multiple columns.
So basically, a csv row has a date value, that must be updated in the record where col_1 and col_2 equals their respective values in the csv rows. If these values don't exist in the database, they are simply ignored.
Is there an elegant way to do this in a single query? This query is part of a spring batch job, so I might not be able to use native postgres syntax, but I'm struggling to even understand the format of the query so I can worry about the syntax later. Would I need multiple update statements? If so, how can I achieve that in the write step of a spring batch job?
EDIT: Adding some sample data to explain process
CSV rows:
date, col_1, col_2
2021-12-30, 'abc', 'def'
2021-05-30, 'abc', 'zzz'
2021-07-30, 'hfg', 'xxx'
I'll need my query to locate a record where col_1='abc' AND col_2=def, then change the date column to 2021-12-30. I'll need to do this for every row, but I don't know how to format the UPDATE query.
You can insert your CSV data into a (temporary) table (say mycsv) and use UPDATE with a FROM clause. For instance:
CREATE TEMP TABLE mycsv (date DATE, col_1 TEXT, col_2 TEXT);
COPY mycsv FROM '/path/to/csv/csv-file.csv' WITH (FORMAT csv);
UPDATE mytable m SET date = c.date
FROM mycsv c WHERE m.col_1 = c.col_1 AND m.col_2 = c.col_2;
Create an Itemwriter implementation, and override the write() method. That method accepts a list of objects, each returned from your ItemProcessor implementation.
In the write method, simply loop through the objects, and call update on each one in turn.
For Example:
In the ItemWriter:
#Autowired
private SomeDao dataAccessObject;
#Override
public void write(List<? extends YourDTO> someDTOs) throws Exception {
for(YourDTO dto: someDTOs) {
dataAccessObject.update(dto);
}
}
In your DAO:
private static final String sql = "UPDATE mytable SET dateField = ? WHERE col_1 = ? and col_2 = ?";
public void update(YourDTO dto) {
Object[] parameters = { dto.getDate(), dto.getCol1(), dto.getCol2()};
int[] types = {Types.DATE, Types.STRING, Types.STRING};
jdbcTemplate.update(sql, parameters, types);
}

Creating multi-column constraints depending on column value

I'm trying to create a constraint on an oracle database that says the following:
If column1 == someValue then the combination of column2 and column3 has to be unique for all entries with column1 == someValue
I'm familiar with the concepts of unique and check constraints, and I've tried expressing the constraint with those constructs. However, I can't seem to find a way to include the condition. Which is why I'm wondering if it is even possible.
The table I want to create constraint for is created by Hibernate mapping the following class hierarchy (most of the attributes ommited for brevity):
class MyClass {
String name;
MyClass parent;
}
class MySubClass extends MyClass {
String businessValue;
}
The classes are mapped using a single table strategy and using different discriminator values for each type. It's a customer requirement that for all instances of MySubClass the combination of name and parent has to be unique (column1 would be the discriminator value). It would be easy to enforce such a constraint on the parent class through a table constraint. However, that constraint must only apply to MySubClass.
There is the possibility of validating the data before entering it into the the database with frameworks such as Hibernate Validator. But since the validation would need database access anyway, a database constraint seems the more performance saving way to do it.
You can't do this with a constraint, but you can do it using a "function-based index" (FBI) like this:
create unique index mytable_idx on mytable
( case when column1 = 'somevalue' then column2 end
, case when column1 = 'somevalue' then column3 end
);
This only creates unique index entries for rows with column1 = 'somevalue', so other rows can contain duplicates but these cannot.

Oracle query Java EE, Entity Manager

If I have an Oracle database, with structure, SCHEMA/TABLE1 SCHEMA/TABLE2 and I want to create a query to select all rows from Table1, would it be,
"Select x from SCHEMA.TABLE1 x"
If you have an entity such as:
#Entity
#Table(schema="SCHEMA", name="TABLE1")
public class Table1Class {
...
}
Then, the following basic JPQL Query would select all the Table1Class entities:
Select x from Table1Class x.
Summing up, you don't need to (not that you can, either) specify schema and table name on JPQL queries, just the class name the table is mapped to.

Resources