How to store collection of values as attributes in DynamoDB table? - java

I have a structure with collection of items inside that need to stored in DynamoDB table. Using current implementation items are stored as JSON but I would like to have them as unique attributes in table. Is it possible using spring-data-dynamodb library?
#Getter
#Setter
#DynamoDBTable(tableName = "orders")
public class Order {
#DynamoDBHashKey
#DynamoDBAutoGeneratedKey
private String id;
#DynamoDBAttribute
private long userId;
#DynamoDBAttribute
private List<Item> items;
}
#Getter
#Setter
#DynamoDBDocument
public class Item {
#DynamoDBAttribute
private String name;
#DynamoDBAttribute
private String value;
}
Expected result:
Table: orders
| id | userId | item_name1 | item_name2 | item_name3 |
| s2 | 234 | item_value1 | item_value1 | item_value3 |

Related

How to fetch data from multiple tables in spring boot using mapping in Spring Boot's JPA repository

I have created four entity classes as:
#Entity
#Table(name = "DashboardRegionCountry")
public class DashboardRegionCountry implements Serializable {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "dashboardId")
private long dashboardId;
#OneToOne(targetEntity = Country.class)
#JoinColumn(name="countryId")
private Country country;
#OneToOne(targetEntity = Region.class)
#JoinColumn(name="regionId")
private Region region;
#ManyToOne()
#JoinColumn(name="dashboardId")
private Dashboard dashboard;
}
#Entity
#Table(name = "Dashboard")
public class Dashboard implements Serializable {
#Id
#Column(name = "dashboardId")
#GeneratedValue(strategy = GenerationType.AUTO)
private Long dashboardId;
#Column(name = "dashboardName")
private long dashboardName;
#OneToMany(mappedBy= dashboard)
private List<DashboardRegionCountry> dashboardRegionCountry;
}
#Entity
#Table(name = "Country")
public class Country implements Serializable {
#Id
#Column(name = "countryId")
#GeneratedValue(strategy = GenerationType.AUTO)
private Long countryId;
#Column(name = "shortName")
private String shortName;
#Column(name = "longName")
private String longName;
}
#Entity
#Table(name = "Region")
public class Region implements Serializable {
#Id
#Column(name = "regionId")
#GeneratedValue(strategy = GenerationType.AUTO)
private Long regionId;
#Column(name = "shortName")
private String shortName;
#Column(name = "longName")
private String longName;
}
And the table schemas for the respective entities are as follows:
DashboardRegionCountry:
+----------------+---------------+
| Field | Type |
+----------------+---------------+
| id(PK) | Number(11) |
| dashboardId(FK)| Number(11) |
| countryId | Number(11) |
| regionId | Number(11) |
+-------------+------------------+
Dashboard:
+----------------+---------------+
| Field | Type |
+----------------+---------------+
| dashboardId(PK)| Number(11) |
| dashboardName | varchar(11) |
+-------------+------------------+
Country:
+-------------+---------------+
| Field | Type |
+-------------+---------------+
| countryId(PK)| Number(11) |
| shortName | Varchar2(10) |
| longName | Varchar2(10) |
+-------------+---------------+
Region:
+-------------+---------------+
| Field | Type |
+-------------+---------------+
| regionId(PK)| Number(11) |
| shortName | Varchar2(10 |
| longName | Varchar2(10) |
+-------------+---------------+
Basically, when user enters the dashboardId then we want to fetch, dashboardDetails along with the Region and respective countries presnt in that region. As stated above, I only have region and country Ids in my table and their names are present in other tables.
I want to display my sample output something like:
{
"dashboardId":20,
"DashboardRegionCountry": [{
"Region":"ASIA",
"dashboardId":["India","China"]
},
{
"Region":"NAM",
"dashboardId":["USA","Canada"]
}
]
}
I am trying to write JPA repository but was wondering is it possible to write something like:
#Repository
public interface DashboardRegionCountryRepository extends JpaRepository<DashboardRegionCountry, Long>{
List<Map<Long,Country>> findRegionBy_RegionId(Long dashboardId);
}
I am trying to fetch all the data in one query, any suggestion will be really helpful
Just get the corresponding DashboardRegionCountry using getById (check the reference documentation) and it will contain both associated Country and Region. If you then don't want to expose all Country and Region information in your entities I suggest you map them to a DTO that would be the model that you want to use while returning something on your controllers.
findByRegion_regionId try this this will work.

Is there any way to set String property of class depending on tablename?

I have two tables in my database, at "retail" schema, with indent column sets:
"vegetable_group":
+------------------+--------------------+
| (varchar) id | (varchar) value |
+------------------+--------------------+
| 1 | good_vegetables |
| 2 | bad_vegetables |
+------------------+--------------------+
"fruit_group":
+------------------+--------------------+
| (varchar) id | (varchar) value |
+------------------+--------------------+
| 3 | good_fruit |
| 4 | bad_fruit |
+------------------+--------------------+
also i have an enum in database type product_type as enum ('fruit', 'vegetable');
this is my entity:
#Data
#Entity
#Table(schema = "retail", name = "vegetable_group")
#SecondaryTables({
#SecondaryTable(schema = "retail", name = "fruit_group",
pkJoinColumns = #PrimaryKeyJoinColumn(name = "id", referencedColumnName = "id")
)
})
public class Product implements Serializable {
private enum ProductType {
vegetable, fruit
}
#Id
#Column(name = "id")
private String id;
#Enumerated(EnumType.STRING)
ProductType productType;
#Column(name = "value")
private String value;
}
and simple ProductRepository
public interface ProductRepository extends JpaRepository<Product, String> {
}
I need to set somehow the value of product.productType depending on the table, from combined data...
Can i somehow simply do that?
Upd.
I'm using #SecondaryTable, because i need to get data from two tables using a single entity. For example, i have a Product with id 99. I don't know whether it is a vegetable or a fruit. The common approach for such process is to create two entities: Fruit and Vegetable and search them by id's. But database structure can't be changed so i use one entity Product, that gets data from both tables by unique id.

create a reference table from two tables

I transform my site to use Java EE and hibernate!
I have 3 tables:
like
id | table | idElement | userId
movie
movie_id | title | duration
videoGame
game_id | title | nbPlayer
and currently 2 class:
#Entity
#Table(name="movie")
public class Movie {
#Id
#GeneratedValue
#Column(name="movie_id")
private Integer id;
private String title;
private int duration;
#Entity
#Table(name="videoGame")
public class Game {
#Id
#GeneratedValue
#Column(name="game_id")
private Integer id;
private String title;
private int nbPlayer;
I do not know how to make my table "like" to link it to one of the two table and the correct id?
example:
table like:
+---+-------+-----------+-------+
|id | table | idElement | userId|
|1 | movie | 1 | 1 |
|1 | game | 5 | 3 |
+---+-------+-----------+-------+
thanks a lot for your help!
Looks like there is no direct way to map your tables to hibernate (At least I am not aware of).
Using inheritance you can produce a similar effect. Movie and Game can be a subclass of another class (say Likable). So that you can use Likable class like below:
#Entity
#Table(name="like")
public class Like {
#Id
#GeneratedValue
#Column(name="like_id")
private Integer id;
#ManyToOne
#JoinColumn(name="likable_id", nullable=false)
private Likable likable;
#ManyToOne
#JoinColumn(name="user_id", nullable=false)
private User user;
}
Likable class will look like below:
#Entity
#Table(name = "likable")
#Inheritance(strategy=InheritanceType.JOINED)
public class Likable {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name = "id")
private int id;
}
Movie class:
#Entity
#Table(name="movie")
#PrimaryKeyJoinColumn(name="id")
public class Movie extends Likable {
private String title;
private int duration;
}
And Game class:
#Entity
#Table(name="videoGame")
#PrimaryKeyJoinColumn(name="id")
public class Game extends Likable {
private String title;
private int nbPlayer;
}

Composite table with Hibernate Envers

I have an application with a composite table holding one extra column. It all works fine, until we add Hibernate Envers (#Audited).
org.hibernate.MappingException: Unable to read the mapped by attribute for responseDomainCodes in no.pack.response.ResponseDomainCode
I am happy to provide more detailed information if necessary, however, at this time I am not sure what would be relevant.
The tables look like this, and is a pretty standard composite key table, with one extra column.
Database schema
+-----------+---------+
| CODE | TYPE |
+-----------+---------+
| category | VARCHAR |
| code | VARCHAR |
+-----------+---------+
|
|
+----------------------+---------+
| RESPONSE_DOMAIN_CODE | TYPE |
+----------------------+---------+
| response_domain_id | KEY |
| code_id | KEY |
| rank | VARCHAR |
+----------------------+---------+
|
|
+--------------------+------+
| RESPONSE_DOMAIN | TYPE |
+--------------------+------+
| response_domain_id | PK |
| response_kind_id | FK |
+--------------------+------+
ResponseDomain.java
#Entity
#Table(name = "responseDomain")
public class ResponseDomain implements Serializable {
#Id
#Column(name = "responseDomain_id")
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#ManyToOne
#JoinColumn(name = "respons_kind_id")
private ResponseKind responseKind;
#OneToMany(fetch = FetchType.EAGER, mappedBy = "pk.responseDomain", cascade = CascadeType.ALL)
private Set<ResponseDomainCode> responseDomainCodes = new HashSet<>();
//Omitted rest.
}
Code.java
#Entity
#Table(name = "code")
public class Code implements Serializable {
#Id
#Column(name = "code_id")
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String category;
private String code;
#OneToMany(fetch = FetchType.EAGER, mappedBy = "pk.code", cascade = CascadeType.ALL)
private Set<ResponseDomainCode> responseDomainCodes = new HashSet<>();
//Omitted rest
}
ResponseDomainCode.java
#Entity
#Table(name = "responseDomain_code")
#AssociationOverrides(value = {
#AssociationOverride(name = "pk.responseDomain",
joinColumns = #JoinColumn(name = "responseDomain_id")),
#AssociationOverride(name = "pk.code",
joinColumns = #JoinColumn(name = "code_id"))
})
public class ResponseDomainCode implements Serializable {
#EmbeddedId
private ResponseDomainCodeId pk = new ResponseDomainCodeId();
#Column(name = "rank")
private String rank;
public ResponseDomainCodeId getPk() {
return pk;
}
public void setPk(ResponseDomainCodeId pk) {
this.pk = pk;
}
public String getRank() {
return rank;
}
public void setRank(String rank) {
this.rank = rank;
}
#Transient
public ResponseDomain getResponseDomain() {
return getPk().getResponseDomain();
}
public void setResponseDomain(ResponseDomain responseDomain) {
this.getPk().setResponseDomain(responseDomain);
}
#Transient
public Code getCode() {
return getPk().getCode();
}
public void setCode(Code code) {
this.getPk().setCode(code);
}
//Omitted rest
}
ResponseDomainCodeId.java
#Embeddable
public class ResponseDomainCodeId implements Serializable {
#ManyToOne
private ResponseDomain responseDomain;
#ManyToOne
private Code code;
public ResponseDomainCodeId() {
}
public ResponseDomain getResponseDomain() {
return responseDomain;
}
public void setResponseDomain(ResponseDomain responseDomain) {
this.responseDomain = responseDomain;
}
public Code getCode() {
return code;
}
public void setCode(Code code) {
this.code = code;
}
//Omitted rest
}
With the help of #adamw I managed to solve this, by changing my mapping.
Instead of using a composite key, a table with its own unique ID was generated.
+----------------------+------------+
| RESPONSE_DOMAIN_CODE | TYPE |
+----------------------+------------+
| id | PK(BIGINT) |
| response_domain_id | BIGINT |
| code_id | BIGINT |
| rank | VARCHAR |
+----------------------+------------+
Now instead of using #Embeddable and #EmbeddedId I have a #ManyToOne and #OneToMany annotation on either side, and query based on ResponseDomain.
This enable full version audit control using Hibernate Envers also in relations like this.
I hope this will be helpful for someone at some point.

JPA - Multiple columns discriminator

I have 3 tables like this in MySQL 5:
| PERSON |
| id | fullName | isEmp | isParent |
| EMPLOYEE |
| personId | code |
| PARENT |
| personId | job |
in which, Employee.personId and Parent.personId are foreign keys pointing to Person.id. An employee can also be a parent and vice versa. So how can I config using Annotation of JPA 2.0/Hibernate 3? Thanks!
If a Person can be both, you can't solve this through inheritance, because Java doesn't allow multiple inheritance. So you'll have to go with Aggregation, which is confusing on a semantic level, because it's has-a-parent instead of is-a-parent. But I'm afraid it's the way you'll have to go:
#Entity
public class Person{
#Id
private Long id;
#OneToOne(optional=true)
private Employee employee;
#OneToOne(optional=true)
private Parent parent;
public boolean isParent(){return parent!=null;}
public boolean isEmployee(){return employee!=null;}
}
#Entity
public class Employee{
#Id
private Long id;
#OneToOne(mappedBy="employee",optional=false)
private Person person;
}
#Entity
public class Parent{
#Id
private Long id;
#OneToOne(mappedBy="parent",optional=false)
private Person person;
}
(getters / setters etc. omitted)

Categories

Resources