Avoid circular self references in hibernate entity - json

I have a Hibernate entity with self references
#Entity
#Table(name = "category")
#NamedQuery(name = "Category.findAll", query = "SELECT c FROM Category c")
public class Category implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(nullable = false, length = 255)
private String name;
#Column(length = 255)
private String description;
#Column(nullable = false, length = 25, columnDefinition = "enum('Category','SubCategory','Indicator')")
private String type;
#ManyToMany
#JoinTable(name = "CategoryHierarchy", joinColumns = #JoinColumn(name = "parentId", referencedColumnName = "id"), inverseJoinColumns = #JoinColumn(name = "childId", referencedColumnName = "id"))
private List<Category> childs;
// getters and setters
}
So, obviously I was facing infinite recursion while deserializing the JSON when I was getting all the entities. So I added
#JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "#id")
above the class name.
But now, the JSON only contains ids or numbers like
{
"success": true,
"messages": [
{
"#id": 1,
"id": 5,
"name": "TestParentCategory ",
"description": "This is test Parent category",
"type": "Category",
"status": "New",
"childs": [
{
"#id": 2,
"id": 6,
"name": "TestChildCategory",
"description": "This is test child category",
"editTime": "2016-03-23T11:40:19",
"editedBy": null,
"createTime": "2016-03-23T11:40:19",
"createdBy": 10,
"type": "SubCategory",
"status": "New",
"childs": [
{
"#id": 3,
"id": 8,
"name": "TestChildCategory",
"description": "This is test child category",
"editTime": "2016-03-23T11:40:20",
"editedBy": null,
"createTime": "2016-03-23T11:40:20",
"createdBy": 10,
"type": "Indicator",
"status": "New",
"childs": [],
"parents": [
2,
{
"#id": 4,
"id": 7,
"name": "TestChildCategory",
"description": "This is test child category",
"editTime": "2016-03-23T11:40:19",
"editedBy": null,
"createTime": "2016-03-23T11:40:19",
"createdBy": 10,
"type": "SubCategory",
"status": "New",
"childs": [
3,
{
"#id": 5,
"id": 9,
"name": "TestChildCategory",
"description": "This is test child category",
"editTime": "2016-03-23T11:40:20",
"editedBy": null,
"createTime": "2016-03-23T11:40:20",
"createdBy": 10,
"type": "Indicator",
"status": "New",
"childs": [],
"parents": [
2,
4
],
"opinions": [],
"timestamp": "2016-03-23T11:40:20",
"edited": "2016-03-23T11:40:20"
}
]
}
],
},
]
}
]
},
2,
4,
3,
5
]
}
I dont want numbers in the array (2, 4, 3, 5) but I want actual objects. How can I do that?
UPDATE
I also went through the question
so is it the only way to do it?

Related

How to save list of nested two separate objects

How to write model class and establish relation between classes. To save and update the below the JSON using spring boot.
inputJSON
{
"modelName": "",
"modelDescription": "",
"recordStatus": true,
"details": [
{
"tMemberDetail": {
"param1": "",
"pn": {
"param1": "",
"param2": ""
},
"an": {
"param1": "",
"param2": ""
},
"p": {
"h": {
"param1": "",
"param2": ""
},
"v": {
"param1": "",
"param2": ""
},
"r": {
"param1": "",
"param2": ""
}
},
"t": {
"param1": ""
}
},
"mattributes": {
"param1": "",
"SP": {
"param1": "",
"param2": ""
},
"EP": {
"param1": "",
"param2": ""
},
"F": {
"Required": false,
"FT": "",
"G": {
"param1": ""
},
"FP": {
"param1": "",
"param2": ""
},
"Pmr": {
"Required": false,
"Details": {
"param1": "",
"param2": ""
}
},
"Pnt": {
"Required": false,
"Details": {
"param1": "",
"param2": ""
}
},
"ASS": {
"Required": false,
"Details": {
"param1": ""
}
},
"NPA": {
"Required": false,
"Details": {
"param1": "",
"param2": ""
}
}
},
"Start": {
"param1": "",
"Loads": {
"param1": ""
}
},
"End": {
"param1": "",
"Loads": {
"param1": ""
}
}
}
}
]
}
I have tried to achieve by writing model class like below
#Setter
#Getter
#ToString
#Entity
#NoArgsConstructor
public class Model extends BaseEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long modelId;
private String modelName;
private String modelDescription;
private RecordStatus recordStatus=RecordStatus.ACTIVE;
}
#Setter
#Getter
#Entity
#NoArgsConstructor
public class TModel extends Model implements Serializable{
private static final long serialVersionUID = 7331603514610649855L;
#OneToMany(cascade = CascadeType.ALL , orphanRemoval = true)
private List<TMember > tMembers ;
}
#Setter
#Getter
#ToString
#Entity
#NoArgsConstructor
public class TMember implements Serializable{
private static final long serialVersionUID = 7331603514610649855L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long tMemberId;
#OneToOne(cascade = CascadeType.ALL , orphanRemoval = true)
private TMemberDetail tMemberDetail;
#OneToOne(cascade = CascadeType.ALL , orphanRemoval = true)
private MemberAttribute memberAttributes;
}
The problem I am facing here is that every time I update call child objects, auto incremental id's are incremented by 1.
If I call get service from another application I get only
modelName, modelDescription, recordStatus but not the entire data.

Managing circular dependency in JSON response

How do I handle the dependency between the two entities? I want to be able to get the games for a player and also players for a game. I am currently trying to do it with #JsonIdentityInfo but the result is not satisfying.
#Entity
#Table(name = "player", uniqueConstraints = { #UniqueConstraint(columnNames = "id") })
#JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Player.class)
public class Player{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "games_admins", joinColumns = { #JoinColumn(name = "player_id") }, inverseJoinColumns = {
#JoinColumn(name = "game_id") })
private Set<Game> games;
#Entity
#Table(name = "game", uniqueConstraints = { #UniqueConstraint(columnNames = "id") })
#JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Game.class)
public class Game{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
#ManyToMany(mappedBy = "games")
private Set<Player> players;
So when I send a GET request to get all of the players I want to receive something like this
[
{
"id": 1,
"name": "Player1",
"games": [
{
"id": 1,
"name": "game1",
"players": [1, 2, 3]
},
{
"id": 2,
"name": "game2",
"players": [1, 3]
},
{
"id": 3,
"name": "game3",
"players": [1, 2]
}
]
},
{
"id": 2,
"name": "Player2",
"games": [
{
"id": 1,
"name": "game1",
"players": [1, 2, 3]
},
{
"id": 3,
"name": "game3",
"players": [1, 2]
}
]
},
{
"id": 3,
"name": "Player3",
"games": [
{
"id": 1,
"name": "game1",
"players": [1, 2, 3]
},
{
"id": 2,
"name": "game2",
"players": [1, 3]
}
]
}
]
So when we reach the "player" again we don't list the games but their ids to avoid the recursion. Same should apply for games.
But what I get is this:
[
{
"id": 1,
"name": "Player1",
"games": [
{
"id": 2,
"name": "game2",
"players": [
1,
{
"id": 3,
"name": "Player3",
"games": [
2,
{
"id": 1,
"name": "game1",
"players": [
{
"id": 2,
"name": "Player2",
"games": [
1,
{
"id": 3,
"name": "game3",
"players": [2, 1]
}
]
},
1,
3
]
}
]
}
]
},
1,
3
]
},
2,
3
]

JsonBackReference not working as expected

I have the next two clases...
Class A
#Entity
#Table(name="ClassA")
public class ClassA
{
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "Id", unique = true, nullable = false)
private Long id;
#Column(name = "Name", nullable = false, length = 50)
private String name;
#JsonManagedReference
#OneToMany(mappedBy="classA")
private List<ClassB> classBList;
}
Class B
#Entity
#Table(name = "ClassB")
public class ClassB
{
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "Id", unique = true, nullable = false)
private Long id;
#Column(name = "Name", nullable = false, length = 50)
private String name;
#JsonBackReference
#ManyToOne
#JoinColumn(name = "ClassAId", nullable = false)
private ClassA classA;
}
When i do a get of all ClassA records from database using REST the result is working like charm:
GET http://localhost:8080/REST/ClassA
[
{
"id": 1,
"name": "VVVV I",
"classB": [
{
"id": 1,
"name": "SSSS I"
},
{
"id": 2,
"name": "QQQQ II",
}
]
},
{
"id": 2,
"name": "RRRR II",
"classB": []
},
{
"id": 3,
"name": "FFFFF III",
"classB": []
},
{
"id": 4,
"name": "QWERR",
"classB": [
{
"id": 3,
"name": "GGGG III",
},
{
"id": 4,
"name": "HHHH IV",
},
{
"id": 5,
"name": "JJJJ V",
}
]
},
{
"id": 5,
"name": "TRRR",
"classB": []
}
]
The problem is when i want to get the list of ClassB, the ClassA is not returning at all...
GET http://localhost:8080/REST/ClassB
[
{
"id": 1,
"name": "SSSS I"
},
{
"id": 2,
"name": "QQQQ II"
},
{
"id": 3,
"name": "GGGG III"
},
{
"id": 4,
"name": "HHHH IV"
},
{
"id": 5,
"name": "JJJJ V"
}
]
I need ClassA (without classB inside of it) be listed when getting list of ClassB
How can i achieve that?
Best regards

json responce is Multiple Array How i can Parse it using Volley

How to Show "Category" , according to Category "Title", & "Price"
in RecyclerView One Row.
my Api url is https://www.paidup.io/api/v1/businesses/212/menu
This Url returns response like:
[{
"category": "Espresso & Coffee",
"items": [{
"title": "Vacuum Coffee",
"size": [{
"label": "medium",
"price": 125
}, {
"label": "large",
"price": 145
}]
}, {
"title": "Cafe Latte",
"size": [{
"label": "small",
"price": 115
}, {
"label": "medium",
"price": 135
}, {
"label": "large",
"price": 150
}]
}, {
"title": "Cafe Mocha",
"size": [{
"label": "small",
"price": 115
}, {
"label": "medium",
"price": 135
}, {
"label": "large",
"price": 150
}]
}, {
"title": "White Mocha",
"size": [{
"label": "small",
"price": 120
}, {
"label": "medium",
"price": 145
}, {
"label": "large",
"price": 155
}]
}, {
"title": "Caramel Macchiato",
"size": [{
"label": "small",
"price": 125
}, {
"label": "medium",
"price": 145
}, {
"label": "large",
"price": 165
}]
}, {
"title": "Coffee De Leche",
"size": [{
"label": "small",
"price": 130
}, {
"label": "medium",
"price": 145
}, {
"label": "large",
"price": 160
}]
}, {
"title": "Cafe-UK Coffee Lava",
"size": null,
"price": 145
}]
}, {
"category": "Frappe",
"items": [{
"title": "Coffee Base",
"size": [{
"label": "small",
"price": 140
}, {
"label": "medium",
"price": 155
}, {
"label": "large",
"price": 170
}]
}, {
"title": "Milk Base",
"size": [{
"label": "small",
"price": 130
}, {
"label": "medium",
"price": 145
}, {
"label": "large",
"price": 160
}]
}, {
"title": "Cream Soda Float w\/Ice-cream",
"size": null,
"price": 140
}]
}, {
"category": "Milk Tea & Juice",
"items": [{
"title": "Milk Tea",
"size": [{
"label": "small",
"price": 105
}, {
"label": "medium",
"price": 120
}]
}, {
"title": "Hot Tea",
"size": null,
"price": 120
}, {
"title": "Italian Soda",
"size": [{
"label": "small",
"price": 105
}, {
"label": "medium",
"price": 120
}, {
"label": "large",
"price": 140
}]
}, {
"title": "Juice",
"size": null,
"price": 105
}]
}, {
"category": "Food",
"items": [{
"title": "Ultimate Chili Con Fries",
"size": null,
"price": 290
}, {
"title": "Nachos",
"size": null,
"price": 290
}, {
"title": "Marble Potato Fondue",
"size": null,
"price": 120
}, {
"title":"Breakfast",
"size":null,
"price":220
}]}]
and my POJO Classes are Like:
package ph.paidup.models;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
/**
* Created by oxiloindia on 3/30/2016.
*/
public class Item {
#SerializedName("title")
#Expose
private String title;
#SerializedName("size")
#Expose
private Object size;
#SerializedName("price")
#Expose
private Integer price;
/**
*
* #return
* The title
*/
public String getTitle() {
return title;
}
/**
*
* #param title
* The title
*/
public void setTitle(String title) {
this.title = title;
}
/**
*
* #return
* The size
*/
public Object getSize() {
return size;
}
/**
*
* #param size
* The size
*/
public void setSize(Object size) {
this.size = size;
}
/**
*
* #return
* The price
*/
public Integer getPrice() {
return price;
}
/**
*
* #param price
* The price
*/
public void setPrice(Integer price) {
this.price = price;
}
}
and another class:
package ph.paidup.models;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Generated;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
/**
* Created by oxiloindia on 3/30/2016.
*/
#Generated("org.jsonschema2pojo")
public class MenuRequest {
#SerializedName("category")
#Expose
private String category;
#SerializedName("items")
#Expose
private List<Item> items = new ArrayList<Item>();
/**
*
* #return
* The category
*/
public String getCategory() {
return category;
}
/**
*
* #param category
* The category
*/
public void setCategory(String category) {
this.category = category;
}
/**
*
* #return
* The items
*/
public List<Item> getItems() {
return items;
}
/**
*
* #param items
* The items
*/
public void setItems(List<Item> items) {
this.items = items;
}
}
Now i want to parse this in my Activity to Get
According to
"category" , needs its
"title" and
"price" in recyclerview
i am Trying to do it Like this way:
public void getInVoice() {
showProgress(true);
String URL="https://www.paidup.io/api/v1/businesses/212/menu";
JsonArrayRequest req = new JsonArrayRequest(Request.Method.GET,URL,null, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
showProgress(false);
VolleyLog.v("Response:%n %s", response);
Gson gson = new GsonBuilder().create();
for (int i = 0; i < response.length(); i++) {
try {
JSONObject jsonObject = new JSONObject();
String desc = jsonObject.getString("category");
JsonParser jsonParser = new JsonParser();
groupItem.items = (List<Item>) jsonParser.parse(String.valueOf(response));
// Create a new adapter with data items
mExpandableAdapter = new BakeryMenuExpandableAdapter(getActivity(), setUpList(groupItem.items)) {
#Override
public void onItemClick(int position, View v) {
}
};
// Attach this activity to the Adapter as the ExpandCollapseListener
mExpandableAdapter.setExpandCollapseListener(new ExpandableRecyclerAdapter.ExpandCollapseListener() {
#Override
public void onListItemExpanded(int position) {
Log.e("CHEEE", "" + position);
}
#Override
public void onListItemCollapsed(int position) {
}
});
// Set the RecyclerView's adapter to the ExpandableAdapter we just created
recyclerView.setAdapter(mExpandableAdapter);
// Set the layout manager to a LinearLayout manager for vertical list
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
} catch (Exception e) {
Log.e("My App", "Could not parse malformed JSON: \"" + response + "\"");
e.printStackTrace();
}
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Activity activity = getActivity();
if (activity != null && isAdded())
showProgress(false);
Toast.makeText(getActivity(), "Something went wrong. please try it again", Toast.LENGTH_SHORT).show();
}
});
// add the request object to the queue to be executed
addToRequestQueue(req, TAG);
}
I tried all Requests to Parse it but couldn't get success.
What should i need to do in Try block to get List of Items for recyclerview
thanks in advance....plz solve it
You have errors in your response callback.
1) You use JsonRequest of volley but you actually want to parse it into a POJO with Gson.
2) you get array of menurequest objects but it seems you handle then as just one MenuRequest
so you don't really need those:
JSONObject jsonObject = new JSONObject();
String desc = jsonObject.getString("category");
JsonParser jsonParser = new JsonParser();
groupItem.items = (List<Item>) jsonParser.parse(String.valueOf(response));
These actually throws different exceptions.
instead you can do:
MenuRequest[] items = gson.fromJson(response.toString(), MenuRequest[].class);
so in items you will endup with an Array of MenuRequest objects
then you can do whatever you need for example:
for(MenuRequest item:items) {
Log.d("test", "item: " +item);
}

json to java object with gson ( object nested with arraylist )

I want to create a object Checklist with the following JSON. But I think the Arraylist categories isn't created. I do not have an exception the debug console enter into bucle when create the object : " Background partial concurrent mark sweep GC freed 165848(5MB) AllocSpace objects, 144(1852KB) LOS objects, 22% free, 55MB/71MB, paused 5.343ms total 67.660ms "
{"type_check":"CAB","description":"simple cabin","categories":[{"category_id":"3","description":"Confort"},{"category_id":"4","description":"Servicios"},{"category_id":"5","description":"AlimentaciĆ³n"},{"category_id":"6","description":"Personal"},{"category_id":"7","description":"Instalaciones"}]}
And the following classes:
Checklist.class
public class Checklist {
private String type_check;
private String description;
private ArrayList<Category> categories;}
Category.class
public class Category {
private int category_id;
private String description;
}
Creating the object:
Gson gson = new GsonBuilder().create();
Checklist check = gson.fromJson(checklist.toString(), Checklist.class);
I must specify the arraylist when I parse the json?? Thanks and have a nice day.
this is how the json would look like with following code
[
{
"type_check": "CAB_0",
"description": "simple cabin",
"categories": [
{
"category_id": 0,
"description": "Description_0"
},
{
"category_id": 1,
"description": "Description_1"
},
{
"category_id": 2,
"description": "Description_2"
},
{
"category_id": 3,
"description": "Description_3"
},
{
"category_id": 4,
"description": "Description_4"
},
{
"category_id": 5,
"description": "Description_5"
},
{
"category_id": 6,
"description": "Description_6"
}
]
},
{
"type_check": "CAB_1",
"description": "simple cabin",
"categories": [
{
"category_id": 0,
"description": "Description_0"
},
{
"category_id": 1,
"description": "Description_1"
},
{
"category_id": 2,
"description": "Description_2"
},
{
"category_id": 3,
"description": "Description_3"
},
{
"category_id": 4,
"description": "Description_4"
},
{
"category_id": 5,
"description": "Description_5"
},
{
"category_id": 6,
"description": "Description_6"
}
]
},
{
"type_check": "CAB_2",
"description": "simple cabin",
"categories": [
{
"category_id": 0,
"description": "Description_0"
},
{
"category_id": 1,
"description": "Description_1"
},
{
"category_id": 2,
"description": "Description_2"
},
{
"category_id": 3,
"description": "Description_3"
},
{
"category_id": 4,
"description": "Description_4"
},
{
"category_id": 5,
"description": "Description_5"
},
{
"category_id": 6,
"description": "Description_6"
}
]
},
{
"type_check": "CAB_3",
"description": "simple cabin",
"categories": [
{
"category_id": 0,
"description": "Description_0"
},
{
"category_id": 1,
"description": "Description_1"
},
{
"category_id": 2,
"description": "Description_2"
},
{
"category_id": 3,
"description": "Description_3"
},
{
"category_id": 4,
"description": "Description_4"
},
{
"category_id": 5,
"description": "Description_5"
},
{
"category_id": 6,
"description": "Description_6"
}
]
},
{
"type_check": "CAB_4",
"description": "simple cabin",
"categories": [
{
"category_id": 0,
"description": "Description_0"
},
{
"category_id": 1,
"description": "Description_1"
},
{
"category_id": 2,
"description": "Description_2"
},
{
"category_id": 3,
"description": "Description_3"
},
{
"category_id": 4,
"description": "Description_4"
},
{
"category_id": 5,
"description": "Description_5"
},
{
"category_id": 6,
"description": "Description_6"
}
]
},
{
"type_check": "CAB_5",
"description": "simple cabin",
"categories": [
{
"category_id": 0,
"description": "Description_0"
},
{
"category_id": 1,
"description": "Description_1"
},
{
"category_id": 2,
"description": "Description_2"
},
{
"category_id": 3,
"description": "Description_3"
},
{
"category_id": 4,
"description": "Description_4"
},
{
"category_id": 5,
"description": "Description_5"
},
{
"category_id": 6,
"description": "Description_6"
}
]
},
{
"type_check": "CAB_6",
"description": "simple cabin",
"categories": [
{
"category_id": 0,
"description": "Description_0"
},
{
"category_id": 1,
"description": "Description_1"
},
{
"category_id": 2,
"description": "Description_2"
},
{
"category_id": 3,
"description": "Description_3"
},
{
"category_id": 4,
"description": "Description_4"
},
{
"category_id": 5,
"description": "Description_5"
},
{
"category_id": 6,
"description": "Description_6"
}
]
}
]
Checklist.Java code is here
public class Checklist {
private String type_check;
private String description;
private ArrayList<Category> categories;
public String getType_check() {
return type_check;
}
public void setType_check(String type_check) {
this.type_check = type_check;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public ArrayList<Category> getCategories() {
return categories;
}
public void setCategories(ArrayList<Category> categories) {
this.categories = categories;
}
}
Category.java code is here
public class Category {
private int category_id;
private String description;
public int getCategory_id() {
return category_id;
}
public void setCategory_id(int category_id) {
this.category_id = category_id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
TestCode.Java code is here
import java.util.ArrayList;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
public class TestCode {
public static void main(String[] args) {
ArrayList<Checklist> list = new ArrayList<Checklist>();
list = createList();
String stringJson = (new Gson()).toJson(list);
System.out.println("##### JSON from a object #######");
System.out.println(stringJson);
System.out.println("###### Convert JSON to object ######");
ArrayList<Checklist> list2 = new ArrayList<Checklist>();
list2 = (new Gson()).fromJson(stringJson,
new TypeToken<ArrayList<Checklist>>() {
}.getType());
System.out.println("####### print out put ######");
for (int i = 0; i < list2.size(); i++) {
Checklist checklist = list2.get(i);
System.out.println(checklist.getType_check() + "");
System.out.println(checklist.getDescription() + "");
ArrayList<Category> categorys = checklist.getCategories();
for (int j = 0; j < categorys.size(); j++) {
Category category = categorys.get(j);
System.out.println(category.getCategory_id() + "");
System.out.println(category.getDescription() + "");
}
}
}
private static ArrayList<Checklist> createList() {
// TODO Auto-generated method stub
ArrayList<Checklist> list = new ArrayList<Checklist>();
for (int i = 0; i < 7; i++) {
Checklist checklist = new Checklist();
checklist.setType_check("CAB_" + i);
checklist.setDescription("simple cabin");
ArrayList<Category> categorys = new ArrayList<Category>();
for (int j = 0; j < 7; j++) {
Category category = new Category();
category.setCategory_id(j);
category.setDescription("Description_" + j);
categorys.add(category);
}
checklist.setCategories(categorys);
list.add(checklist);
}
return list;
}
}