Merging multiple LiveData sources? - java

To make it easier to visualize my problem I drew the following:
I am using a RoomDatabase, a Repository, a Viewmodel and Livedata. Areas have a 1 to n relationship with Gateways and Gateways a 1 to n relationship with Items.
I created both an AreaWithGateways entity and a GatewayWithItems entity.
Items can move from a gateway to another, which is why I observe them with Livedata to keep track of which Gateway they're in. My problem now is that I found myself in need to also keep track of which Items are in which Areas and I can't figure out how to do that.
I've thought of merging the LiveData of each Gateway together and observing that using MediatorLiveData but I didn't really understand how to use it.
Or maybe it's possible to create an Entity AreaWithGatewayswithItems?
Any insight would be appreciated
Edit: I am adding some code to make the problem a bit clearer
This is the Area Entity
#Entity(tableName = "area_table")
public class Area {
#PrimaryKey(autoGenerate = false)
private int areaId;
private String areaName;
private float wertX;
private float wertY;
private Boolean isDrawn;
public int getAreaId() {
return areaId;
}
public void setAreaId(int areaId) {
this.areaId = areaId;
}
public String getAreaName() {
return areaName;
}
public float getWertX() {
return wertX;
}
public float getWertY() {
return wertY;
}
public Boolean getDrawn() {
return isDrawn;
}
public Area(int areaId, String areaName, float wertX, float wertY, Boolean isDrawn) {
this.areaId = areaId;
this.areaName = areaName;
this.wertX = wertX;
this.wertY = wertY;
this.isDrawn = isDrawn;
}
}
The Gateway Entity:
#Entity(tableName = "gateway_table")
public class Gateway {
private float temp;
private String title;
private int areaId;
#PrimaryKey(autoGenerate = false)
private int gatewayId;
public int getGatewayId() {
return gatewayId;
}
public void setGatewayId(int gatewayId) {
this.gatewayId = gatewayId;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public float getTemp() {
return temp;
}
public void setTemp(float temp) {
this.temp = temp;
}
public int getAreaId() {
return areaId;
}
public Gateway(int areaId, int gatewayId, String title) {
this.title = title;
this.areaId = areaId;
this.gatewayId = gatewayId;
}
}
And the "Item" Entity:
#Entity(tableName = "cow_table")
public class Cow {
private int age;
private String sex;
private String name;
private boolean drawn;
private int gatewayId;
private String raceId;
#PrimaryKey(autoGenerate = false)
private int cowId;
public int getCowId() {
return cowId;
}
public void setCowId(int cowId) {
this.cowId = cowId;
}
public String getName() {
return name;
}
public boolean isDrawn() {
return drawn;
}
public int getAge() {
return age;
}
public String getSex() {
return sex;
}
public void setDrawn(boolean drawn) {
this.drawn = drawn;
}
public int getGatewayId() {
return gatewayId;
}
public String getRaceId() {
return raceId;
}
public Cow(int age, int cowId, int gatewayId,String name, String raceId, String sex, boolean drawn) {
this.age = age;
this.cowId = cowId;
this.sex= sex;
this.name = name;
this.drawn = drawn;
this.gatewayId = gatewayId;
this.raceId = raceId;
}
}
And this is the relation "AreaWithGateways":
public class AreaWithGateways {
#Embedded
private Area area;
#Relation(parentColumn = "areaId",
entityColumn = "areaId")
private List<Gateway> gatewayList;
public Area getArea() {
return area;
}
public List<Gateway> getGatewayList() {
return gatewayList;
}
public AreaWithGateways(Area area, List<Gateway> gatewayList) {
this.area = area;
this.gatewayList = gatewayList;
}
}
As well as GatewaysWithCows:
public class GatewayWithCows {
#Embedded
private Gateway gateway;
#Relation(parentColumn = "gatewayId",
entityColumn = "gatewayId")
private List<Cow> cowList;
public Gateway getGateway() {
return gateway;
}
public List<Cow> getCowList() {
return cowList;
}
public GatewayWithCows(Gateway gateway, List<Cow> cowList) {
this.gateway = gateway;
this.cowList = cowList;
}
}
I've been trying to find a way of getting all of the "items" in an Area as Livedata but still can't figure it out.
I feel like I should somehow use AreaWithGateways to add the LiveData items together but I can't reach the items through the gateways, it has to be the other way around.

Or maybe it's possible to create an Entity AreaWithGatewayswithItems?
Not an Entity as these are used to define tables BUT via POJO's using #Embedded and #Relation annotation (e.g. your GatewayWithCows is a POJO).
I feel like I should somehow use AreaWithGateways to add the LiveData items together but I can't reach the items through the gateways, it has to be the other way around.
You basically use a hierarchical approach but POJO's so as you have GatewayWithCows then relate to this from Area as per :-
class AreaWithGatewayWithCows {
#Embedded
Area area;
#Relation(entity = Gateway.class, parentColumn = "areaId",
entityColumn = "areaId")
List<GatewayWithCows> gatewayWithCowsList;
}
Note I missed the s after Gateway for the class name (and as such in the query below)
Note the use of entity = Gateway.class is required as the relationship is via the Gateway NOT via the GatewayWithCows (which isn't a table).
The Query Dao could be as simple as :-
#Query("SELECT * FROM area_table")
List<AreaWithGatewayWithCows> getAreaWithGatewaysWithCows();
amended accordingly for LiveData.
note that if you use JOINS in the query then the any clauses such as WHERE will only affect the Area's, not the underlying Gateways and Cows. That is irrespective of the query #Relation builds each Area with ALL Gateways related to that Area; and each Gateway gets ALL the Cows related to that Gateway.

Related

How to model this relation using Java OOP concepts

I have this condition (property rent system, rent is counted per night)
Owner has one or more property. Property has description, price, and isOccupied attribute.
The property can be: hotel (with 3 room types), flat/apartment, and house for homestay.
Through a registry function, a customer can order one or more property available at certain date.
Here are the pre-defined conditions for registry function:
There are 2 registered owners and customers in the system.
Owner 1 has 10 hotel rooms (standard type) for US$30 per night and 3 hotel rooms (suite type) for US$60 per night.
Owner 2 has 3 apartments for US$70 per night and 5 homestay house for US$20 per night.
Customers can rent one or more owner's property for a certain date.
To model the property, I use inheritance concept. For now, it looks something like this.
Property.java
public class Property {
private String description;
private int propertyPrice;
private String ownerName; // should it be here? or should it be made in another class?
private boolean isOccupied;
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getPropertyPrice() {
return propertyPrice;
}
public void setPropertyPrice(int propertyPrice) {
this.propertyPrice = propertyPrice;
}
}
Hotel.java
public class Hotel extends Property {
private String[] roomType;
private int[] roomCount;
public Hotel(){
this.roomType = new String[]{"Standard", "Deluxe", "Suite"};
this.roomCount = new int[]{0, 0, 0};
}
public String[] getRoomType() {
return roomType;
}
public void setRoomType(String[] roomType) {
this.roomType = roomType;
}
public int[] getRoomCount() {
return roomCount;
}
public void setRoomCount(int[] roomCount) {
this.roomCount = roomCount;
}
}
Apartment.java
public class Apartment extends Property {
private int roomCount;
public int getRoomCount() {
return roomCount;
}
public void setRoomCount(int roomCount) {
this.roomCount = roomCount;
}
}
Homestay.java
public class HomestayRoom extends Property {
private String parentName;
public String getParentName() {
return parentName;
}
public void setParentName(String parentName) {
this.parentName = parentName;
}
}
What makes me confused is, how can I define the pre-defined conditions for registry to model owner-property relation? Should I make the owner at another class? If so, how can I relate the properties and its owner?
Most of what you have done is correct, but you could also have a property type enum
public enum PropertyType{
HOTEL,APARTMENT,HOMESTAY
}
Now you're super class would be
public class Property {
private String description;
private int propertyPrice;
private String ownerName;
private boolean isOccupied;
private PropertyType pt;
....
}
A constructor for hotel would be
public Hotel(){
this.roomType = new String[]{"Standard", "Deluxe", "Suite"};
this.roomCount = new int[]{0, 0, 0};
super(PropertyType.HOTEL);
}
Similarly you could have constructors for Homestay and Apartment, with the extra line of super(PropertyType.HOMESTAY) and super(PropertyType.APARTMENT) respectively.

How to retrieve data using spring rest API in an insensitive case way?

I am making a Rest API with Spring Boot.
I have a method like this in my controller:
#GetMapping("/dead")
#ResponseBody
public ResponseEntity<List<DeadEntity>> getDeadByCountryRegion(#RequestParam(value = "country") String countryRegion) {
List<DeadEntity> entity = serviceDead.findEntityByCountryRegion(countryRegion);
return new ResponseEntity<>(entity, HttpStatus.OK);
}
and my url looks like: http://localhost:8080/api/v1/dead/?country=Russia
but I want to be able get data with this url too. http://localhost:8080/api/v1/dead/?country=russia
What should I do? Thanks.
Entity
public class DeadEntity implements Serializable {
#Id
private Long id;
private String provinceState;
private String countryRegion;
private String lat;
private String lon;
private int latestTotalCases;
private int diffFromPrevDay;
public DeadEntity() {
}
public DeadEntity(Long id, String provinceState, String countryRegion, String lat, String lon, int latestTotalCases, int diffFromPrevDay ) {
this.id = id;
this.provinceState = provinceState;
this.countryRegion = countryRegion;
this.lat = lat;
this.lon = lon;
this.latestTotalCases = latestTotalCases;
this.diffFromPrevDay = diffFromPrevDay;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public int getLatestTotalCases() {
return latestTotalCases;
}
public void setLatestTotalCases(int latestTotalCases) {
this.latestTotalCases = latestTotalCases;
}
public int getDiffFromPrevDay() {
return diffFromPrevDay;
}
public void setDiffFromPrevDay(int diffFromPrevDay) {
this.diffFromPrevDay = diffFromPrevDay;
}
public String getProvinceState() {
return provinceState;
}
public void setProvinceState(String provinceState) {
this.provinceState = provinceState;
}
public String getCountryRegion() {
return countryRegion;
}
public void setCountryRegion(String countryRegion) {
this.countryRegion = countryRegion;
}
public String getLat() {
return lat;
}
public void setLat(String lat) {
this.lat = lat;
}
#JsonProperty("long")
public String getLon() {
return lon;
}
public void setLon(String lon) {
this.lon = lon;
}
}
I get data from CSV remote file
private void fillEntityProperties(Iterable<CSVRecord> newRecord, List<DeadEntity> newEntity) {
for (CSVRecord record : newRecord) {
DeadEntity locationStats = new DeadEntity();
for (long j = 0; j <= newEntity.size(); j++)
locationStats.setId(j);
locationStats.setProvinceState(record.get("Province/State"));
locationStats.setCountryRegion(record.get("Country/Region")); //The country name comes from remote data source in Uppercase mode
locationStats.setLat(record.get("Lat"));
locationStats.setLon(record.get("Long"));
int latestCases = Integer.parseInt(record.get(record.size() - 1));
int prevDayCases = Integer.parseInt(record.get(record.size() - 2));
locationStats.setLatestTotalCases(latestCases);
locationStats.setDiffFromPrevDay(latestCases - prevDayCases);
newEntity.add(locationStats);
saveDeadInDB(locationStats);
}
}
For query parameters it is not your url the problem
#GetMapping("/dead")
#ResponseBody
public ResponseEntity<List<DeadEntity>> getDeadByCountryRegion(#RequestParam(value = "country") String countryRegion) {
List<DeadEntity> entity = serviceDead.findEntityByCountryRegion(countryRegion);
return new ResponseEntity<>(entity, HttpStatus.OK);
}
and my url looks like:
http://localhost:8080/api/v1/dead/?country=Russia
but I want to be able get data with this url too.
http://localhost:8080/api/v1/dead/?country=russia
It would be a problem if you wanted as url the http://localhost:8080/api/v1/dead/?COUNTRY=russia
So the value of the query parameter is not something the #RequestParam cares about.
However that could be handled on your DB level on how you make your queries, and there is something that you can do to make that case incensitive.
Declare in your JPA repository a method with name findByCountryRegionIgnoreCase(countryRegion);
instead of findByCountryRegion(countryRegion)
and fire that on your controller where you execute the serviceDead.findEntityByCountryRegion(countryRegion);
Edit: Corrected repository method names

Best practice for naming and using table and view entity in java and mysql

I am developing a software via JavaFX, using MVC design pattern.
In javaFX to sync view with data I use property fields(like StringProperty, IntegerProperty, ...) and ObservableListcollection.
Also I am using JPA library.
Consider I have two tables in DB, One is city and another is province.
province to city has one to many relationship.
First question:
If I create a view with all data from city and province, what should be the name of that view?
It should be city_vm?
Or I should change table names to citybase and provincebase or something like this? and after that change the view name to city?
Second question :
I want to map all of them into real entities, I want to map the tables(city and province tables) for insertion data and use view entity for selections and displaying data.
Also note that I have a separate class for each of them(additional from their entity class) to achieve advantage of property fields(like StringProperty, IntegerProperty, .... )
This is City class ( Not mapped, with Property fields)
public class City {
private int city_id;
private StringProperty name;
private FloatProperty asl_ft;
private FloatProperty asl_mt;
private FloatProperty sdb_fh;
private FloatProperty sdb_cs;
private FloatProperty swd_fh;
private FloatProperty swd_cs;
private FloatProperty wdb_fh;
private FloatProperty wdb_cs;
private ProvinceEntity province;
public City(String name, Float asl_ft, Float asl_mt, Float sdb_fh,
Float sdb_cs, Float swd_fh,
Float swd_cs, Float wdb_fh, Float wdb_cs) {
this.name = new SimpleStringProperty(name);
this.asl_ft = new SimpleFloatProperty(asl_ft);
this.asl_mt = new SimpleFloatProperty(asl_mt);
this.sdb_fh = new SimpleFloatProperty(sdb_fh);
this.sdb_cs = new SimpleFloatProperty(sdb_cs);
this.swd_fh = new SimpleFloatProperty(swd_fh);
this.swd_cs = new SimpleFloatProperty(swd_cs);
this.wdb_fh = new SimpleFloatProperty(wdb_fh);
this.wdb_cs = new SimpleFloatProperty(wdb_cs);
}
public City() {
}
#Override
public String toString() {
return name.getValue().toString();
}
public StringProperty nameStringProperty() {
return name;
}
public FloatProperty asl_ft_FloatProperty() {
return asl_ft;
}
public FloatProperty asl_mt_FloatProperty() {
return asl_mt;
}
public FloatProperty sdb_fh_FloatProperty() {
return sdb_fh;
}
public FloatProperty sdb_cs_FloatProperty() {
return sdb_cs;
}
public FloatProperty swd_fh_FloatProperty() {
return swd_fh;
}
public FloatProperty swd_cs_FloatProperty() {
return swd_cs;
}
public FloatProperty wdb_fh_FloatProperty() {
return wdb_fh;
}
public FloatProperty wdb_cs_FloatProperty() {
return wdb_cs;
}
public String getName() {
return this.name.get();
}
public Float getAslFT() {
return asl_ft.get();
}
public Float getAslMT() {
return asl_mt.get();
}
public Float getSdbFH() {
return sdb_fh.get();
}
public Float getSdbCS() {
return sdb_cs.get();
}
public Float getSwdFH() {
return swd_fh.get();
}
public Float getSwdCS() {
return swd_cs.get();
}
public Float getWdbFH() {
return wdb_fh.get();
}
public Float getWdbCS() {
return wdb_cs.get();
}
public void setName(String name) {
this.name.set(name);
}
public void setAsl_ft(Float asl_ft) {
this.asl_ft.set(asl_ft);
}
public void setAsl_mt(Float asl_mt) {
this.asl_mt.set(asl_mt);
}
public void setSdb_fh(Float sdb_fh) {
this.sdb_fh.set(sdb_fh);
}
public void setSdb_cs(Float sdb_cs) {
this.sdb_cs.set(sdb_cs);
}
public void setSwd_fh(Float swd_fh) {
this.swd_fh.set(swd_fh);
}
public void setSwd_cs(Float swd_cs) {
this.swd_cs.set(swd_cs);
}
public void setWdb_fh(Float wdb_fh) {
this.wdb_fh.set(wdb_fh);
}
public void setWdb_cs(Float wdb_cs) {
this.wdb_cs.set(wdb_cs);
}
}
And here its entity class named CityEntity :
#Entity
#Table(name = "city")
public class CityEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "city_id", nullable = false)
private int city_id;
#Column(name = "city_sn", nullable = false)
private String name;
#Column(name = "asl_ft", nullable = false)
private Float asl_ft;
#Column(name = "asl_mt", nullable = false)
private Float asl_mt;
#Column(name = "sdb_fh", nullable = false)
private Float sdb_fh;
#Column(name = "sdb_cs", nullable = false)
private Float sdb_cs;
#Column(name = "swb_fh", nullable = false)
private Float swb_fh;
#Column(name = "swb_cs", nullable = false)
private Float swb_cs;
#Column(name = "wdb_fh", nullable = false)
private Float wdb_fh;
#Column(name = "wdb_cs", nullable = false)
private Float wdb_cs;
#ManyToOne
#JoinColumn(name = "fk_province$city")
private ProvinceEntity province;
#Override
public String toString() {
return name;
}
public String getName() {
return this.name;
}
public Float getAslFT() {
return asl_ft;
}
public Float getAslMT() {
return asl_mt;
}
public Float getSdbFH() {
return sdb_fh;
}
public Float getSdbCS() {
return sdb_cs;
}
public Float getSwbFH() {
return swb_fh;
}
public Float getSwbCS() {
return swb_cs;
}
public Float getWdbFH() {
return wdb_fh;
}
public Float getWdbCS() {
return wdb_cs;
}
public void setName(String name) {
this.name = name;
}
public void setAsl_ft(Float asl_ft) {
this.asl_ft = asl_ft;
}
public void setAsl_mt(Float asl_mt) {
this.asl_mt = asl_mt;
}
public void setSdb_fh(Float sdb_fh) {
this.sdb_fh = sdb_fh;
}
public void setSdb_cs(Float sdb_cs) {
this.sdb_cs = sdb_cs;
}
public void setSwb_fh(Float swd_fh) {
this.swb_fh = swd_fh;
}
public void setSwb_cs(Float swd_cs) {
this.swb_cs = swd_cs;
}
public void setWdb_fh(Float wdb_fh) {
this.wdb_fh = wdb_fh;
}
public void setWdb_cs(Float wdb_cs) {
this.wdb_cs = wdb_cs;
}
}
From the start it should be three class for each entity.
One to use advantage of property fields.( City in this example),one for view to select data(combination of city and province),and the last one for table(in this example the city table)
Now If I want to map the city table and city view in my project and use it; What is the best practice for naming convention in Java and Mysql.

Database access Java

I've got the following question. I got a little application which saves payments, dates and persons inside a database. Now I got the following POJO class:
public class Payment implements Serializable {
private int id;
private double payment;
private Date datum;
private String usage;
private String category;
private int importance;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public double getPayment() {
return payment;
}
public void setPayment(double payment) {
this.payment = payment;
}
public Date getDatum() {
return datum;
}
public void setDatum(Date datum) {
this.datum = datum;
}
public String getUsage() {
return usage;
}
public void setUsage(String usage) {
this.usage = usage;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public int getImportance() {
return importance;
}
public void setImportance(int importance) {
this.importance = importance;
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("ID: ");
sb.append(id);
sb.append("\nPAYMENT: ");
sb.append(payment);
sb.append("\nDATE: ");
sb.append(datum);
sb.append("\nUSAGE: ");
sb.append(usage);
sb.append("\nCATEGORY: ");
sb.append(category);
sb.append("\nIMPORTANCE: ");
sb.append(importance);
return sb.toString();
}
}
So, I got also a class for my dates and persons. The question I've got is the following: Should I create for every Table in my database(in Java the Payment.class , Date.class and Person.class) a own transaction/access class which supports an .saveOrUpdate(), .list() or .delete() function?So maybe I got than a PaymentRansaction.class or an PersonTransaction.class.
Thanks for every help :)
It depends.
Do you have one table with transactions, then one model should be sufficient.
Create methods to create the transactions for you depending on Payment or Person.
BUT
If you have more then 1 table go for multiple classess, each table it's own class.

select and deselect parameters as output to JSON ,depending up on the incoming request in java

For example I have an incoming request with URL: "/cid/{cid}/{action}"
For path variable {action} I can have two values i.e. {action}: 1)list 2)tile
My POJO class with parameters for JSON output is below:
public class Area {
private Integer aId;
private String aName;
private Integer allSpaces;
private Integer violated;
private Integer percent;
private Integer level;
private List<Space> space = new ArrayList<Space>(); // this List should be depend on condition
public Area(Integer aId, String aName, Integer allSpaces, Integer violated, Integer percent, Integer level) {
this.aId = aId;
this.aName = aName;
this.allSpaces = allSpaces;
this.level = level;
this.violated = violated;
this.percent = percent;
}
public Integer getaId() {
return aId;
}
public void setaId(Integer aId) {
this.aId = aId;
}
public String getaName() {
return aName;
}
public void setaName(String aName) {
this.aName = aName;
}
public Area addSpace(Space s) {
space.add(s);
return this;
}
public List<Space> getSpace() {
return space;
}
public void setSpace(List<Space> space) {
this.space = space;
}
public Integer getAllSpaces() {
return allSpaces;
}
public void setAllSpaces(Integer allSpaces) {
this.allSpaces = allSpaces;
}
public Integer getViolated() {
return violated;
}
public void setViolated(Integer violated) {
this.violated = violated;
}
public Integer getPercent() {
return percent;
}
public void setPercent(Integer percent) {
this.percent = percent;
}
public Integer getLevel() {
return level;
}
public void setLevel(Integer level) {
this.level = level;
}
}
My output should not consist the parameter private List space = new ArrayList() for action =list but show it for action=tile.
It will of great help if any body can help me with this.
If the class gets serialized, and you want to exclude space from serialization to JSON, you can mark it as transient.
private transient List<Space> space = new ArrayList<Space>();
In the case where you would like to decide if this happens or not, you can subclass Area
So your controller would either invoke ListArea or TileArea.
I got the answer for my question
I intialized private List<Space> space = null; instead of private List<Space> space = new ArrayList<Space>();
and added #JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) on top of my pojo like below
#JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
public class Area {
now the parameters whose value==null will not be included in the serialized output, but I can intialize it dynamically by using constructur and retrive to output if required.

Categories

Resources