I am new to MongoDB and NoSQL databases at all and have some issues to working with MongoDB driver.
I don't properly understand how to get a sub-array/list from document and reinsert data in it.
This is my JSON/BSON object which i can easy save in MongoDB.
{
"_id": {
"$oid": "5757df25612c2445af329111"
},
"shop": {
"category": [
{
"MobilePhones": [
]
},
{
"TV-sets": [
]
},
{
"Motherboards": [
]
}
]
}
}
Now i need to get an Array of Categories from my Shop, get object as MobilePhones/TV-sets/Motherboards category from this array/list as i write in my java POJO class.
public class Category extends BasicDBObject implements Serializable {
private List<Goods> goodsList;
private BasicDBObject basicDBObject;
public BasicDBObject getBasicDBObject() {
return basicDBObject;
}
public void setBasicDBObject(BasicDBObject basicDBObject) {
this.basicDBObject = basicDBObject;
}
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Goods> getGoodsList() {
return goodsList;
}
public void setGoodsList(List<Goods> goodsList) {
this.goodsList = goodsList;
}
public Category(String name){
this.name = name;
}
public Category(){}
}
And insert goods into this category as i write in
public class Goods extends BasicDBObject implements Serializable {
private String title;
private int price;
private String status;
private BasicDBObject basicDBObject;
public BasicDBObject getBasicDBObject() {
return basicDBObject;
}
public void setBasicDBObject(BasicDBObject basicDBObject) {
this.basicDBObject = basicDBObject;
}
public Goods(String title, int price, String status) {
this.title = title;
this.price = price;
this.status = status;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}
In this way i get/create collection at database
DBCollection collection = db.getCollection("shop");
BasicDBObject dbObject = new BasicDBObject();
dbObject.put("shop", shop.createCategoriesWithGoods());
collection.insert(dbObject);
But this way doesn't help me to get category as
DBCollection collection = db.getCollection("MobilePhones");
This is because a collection is a table (in SQL terms) so db.getCollection("MobilePhones"); is looking for a "table" called MobilePhones.
You have saved your data into a collection called "Shop". You need to call getCollection("Shop") then you can perform whatever operations you need to on the data.
Related
this problem only occurs when I get the data from the database, the application is replacing the _ with . this only happens when I get the record from the database
data in database
[{"nombre": "pablo", "pais(codigo)": "52", "telefono": "", "saldo_total": "10"}, {"nombre": "pablo", "pais(codigo)": "52", "telefono": "", "saldo_total": "10"}]
entity in java code
#EnableMongoRepositories
#Document(collection = "data")
public class DataEntity extends BaseMongoEntity {
#Id
private String id;
#Field(value = "company_id")
private int companyId;
private String name;
private String url;
private List<String> variables;
private List<Object> info;
public DataEntity() {
super();
// TODO Auto-generated constructor stub
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public int getCompanyId() {
return companyId;
}
public void setCompanyId(int companyId) {
this.companyId = companyId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public List<String> getVariables() {
return variables;
}
public void setVariables(List<String> variables) {
this.variables = variables;
}
public List<Object> getInfo() {
return info;
}
public void setInfo(List<Object> info) {
this.info = info;
}
}
query to find the record in database
public DataEntity findById(String id) {
ObjectId idO = new ObjectId(id);
Query query = new Query(Criteria.where("_id").is(idO));
return mongoTemplate.findOne(query, DataEntity.class);
}
image of data obtained in object format
only happens when the record is obtained but not when saving data in the database.
Below is my JSON data. I want to convert this to POJOs to store the Name,id,profession in a header table and the respective Jsonarray field in a child table.
JSON:
{
"Name": "Bob",
"id": 453345,
"Profession": "Clerk",
"Orders": [
{
"Item": "Milk",
"Qty": 3
},
{
"Item": "Bread",
"Qty": 3
}
]
}
Entity classes:
public class User {
private String name;
private Integer id;
private String Profession;
private JsonArray Orders;
private UserCart userCart;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getProfession() {
return Profession;
}
public void setProfession(String profession) {
Profession = profession;
}
public JsonArray getOrders() {
return Orders;
}
public void setOrders(JsonArray orders) {
Orders = orders;
}
public UserCart getUserCart() {
return userCart;
}
public void setUserCart(UserCart userCart) {
this.userCart = userCart;
}
}
public class UserCart {
private String item;
private Integer qty;
public String getItem() {
return item;
}
public void setItem(String item) {
this.item = item;
}
public Integer getQty() {
return qty;
}
public void setQty(Integer qty) {
this.qty = qty;
}
}
But when I do below; I get error
Cannot deserialize instance of org.json.JSONArray out of START_ARRAY
token
User user = new User();
JsonNode data = new ObjectMapper().readTree(jsonString);
user = headerMap.readValue(data.toString(), User.class);
How do I go about assigning the entire JSON to both the Java objects ?
Use List<UserCart> for array data in json and use #JsonProperty for mapping different json node name to java object field. No need to use extra field (JsonArray Orders) anymore.
#JsonProperty("Orders")
private List<UserCart> userCart;
I know there are a few questions on stackoverflow regarding this problem. But I have have been spending hours trying to resolve this error without any success.
I am using the mysql database to store the values.
I keep on getting the error message from the
com.example.springboot.Recipe file.
This is springboot recipe file
package com.example.springboot;
import com.example.springboot.Recipe;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
#Entity // This tells Hibernate to make a table out of this class
public class Recipe {
public Recipe(){
}
public Recipe(Integer id, String name, String description, String type, Integer preptime, Integer cooktime, String content, Integer difficulty){
this.id = id;
this.name = name;
this.description = description;
this.type = type;
this.preptime = preptimee;
this.cooktime = cooktime;
this.content = content;
this.difficulty = difficulty;
}
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;
private String name;
private String description;
private String type;
private Integer preptime;
private Integer cooktime;
#Column(columnDefinition = "TEXT")
private String content;
private Integer difficulty;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTitle() {
return name;
}
public void setTitle(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Integer getDifficulty() {
return difficulty;
}
public void setDifficulty(Integer difficulty) {
this.difficulty = difficulty;
}
public Integer getCookingtime() {
return cooktime;
}
public void setCookingtimeime(Integer cooktime) {
this.cooktime = cooktime;
}
public Integer getPreparationtime() {
return preptime;
}
public void setPreparationtime(Integer preptime) {
this.preptime = preptime;
}
}
Main Controller:
#PutMapping("/recipes/edit/{id}")
void updateRecipe2(#PathVariable int id, #RequestBody Recipe recipe ) {
Recipe recipe_ = recipeRepository.findById(id).get();
recipe_.setTitle(recipe.getTitle());
System.out.println("sss " + recipe.getname());
System.out.println("change");
recipeRepository.save(recipe_);
}
service.ts:
updateRecipe2 (id: number, recipe: any): Observable<any > {
const url = `${this.usersUrl}/edit/${id}`;
return this.http.put(url ,recipe);
}
where the updateRecipe2 gets called:
save(): void {
const id = +this.route.snapshot.paramMap.get('name');
this.recipeService.updateRecipe2(id, this.recipes)
.subscribe(() => this.gotoUserList());
}
as soon as the user clicks save this functions saves the changes made.
I hope the code snippets that I provided are enough to help solve the problem.
Thank you in advance.
I am building a rest api with spring boot and I am using angularjs as it's frontend. I am pretty new to web-development.
You are sending a list of recipes to an api endpoint that expects a single recipe object.
Your options are:
Send only one recipe object at a time, for example:
this.recipeService.updateRecipe2(id, this.recipes[0])
OR: create a new API endpoint to accept a list of recipes, to edit them in "batch"
#PutMapping("/recipes/edit")
void updateRecipes(#RequestBody List<Recipe> recipe ) {
my Example:
Use:
#PostMapping
Code:
public void setTransacciones(List<Transacciones> transacciones) {
this.transacciones = transacciones;
}
CodeBean:
public class Transacciones {
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
private String text;
}
Post(raw):
{
"transacciones" : [ {"text" : "1"}, {"text" : "2"} ]
}
Result:
{
"transacciones": [
{
"transaccionId": 2,
"text": "1"
},
{
"transaccionId": 3,
"text": "2"
}
]
}
BINGO!!
I would like to iterate Products and get the list of name,code and price and set in my Model class. Any help would be really appreciated - how can I iterate this. When I use obj.get("Products") - it just printing as string - got stuck to iterate.
{
"id": "skd3303ll333",
"Products": [{
"name": "apple",
"code": "iphone-393",
"price": "1939"
},
{
"name": "ipad",
"code": "ipad-3939",
"price": "900"
}
]
}
#PostMapping(path="/create", consumes=MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Object> create(#RequestBody Map<String, Object> obj ) {
System.out.println("Products :" + obj.get("Products"));
}
There are two ways to do this,
1) By type casting (personally i will not prefer this)
List<Map<Object,Object>> productslist = (List<Map<Object, Object>>) obj.get("products");
for(Map entry: productslist) {
for(Object s: entry.keySet()) {
System.out.println(s.toString());
System.out.println(entry.get(s).toString());
}
}
2) Mapping directly to Model class, for this approach you need Jackson library in buildpath
#JsonIgnoreProperties(unknown =true)
public class Customer {
#JsonProperty("id")
private String id;
#JsonProperty("products")
private List<Products> products;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public List<Products> getProducts() {
return products;
}
public void setProducts(List<Products> products) {
this.products = products;
}
}
#JsonIgnoreProperties(unknown =true)
class Products{
#JsonProperty("name")
private String name;
#JsonProperty("code")
private String code;
#JsonProperty("price")
private String price;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
}
Controller
public ResponseEntity<Object> create(#RequestBody Customer obj ) {
You need POJO structure with two classes:
public class Product {
private String name;
private String code;
private int price;
}
public class ProductsGroup {
private long id;
private List<Product> products;
// getters/setters
}
And change your method signature to:
#PostMapping(path="/create", consumes=MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<ProductsGroup> create(#RequestBody ProductsGroup productGroup)
{
System.out.println("Products :" + productGroup.getProducts());
}
You are trying to process the json using a Map<String, Object> obj, which could be possible in some way, but mostly what you want to do is define a single or multiple POJO classes. These represent the json.
public class IdWrapper {
private String id;
#JsonProperty("Products")
private List<Product> products;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public List<Product> getProducts() {
return products;
}
}
public class Product {
private String name;
private String code;
private String price;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
}
And in you controller like this:
#RestController
#RequestMapping("test")
public class DemoController {
#PostMapping()
public void test(#RequestBody IdWrapper productsWrapper) {
System.out.println();
}
}
#Entity
public class Category {
#Id
private Long id;
private String name;
private String description;
#Load
private List<Ref<Subcategory>> subcategories = new ArrayList<Ref<Subcategory>>();
#Load
private Ref<Image> image;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public List<Subcategory> getSubcategories() {
List<Subcategory> scs = new ArrayList<Subcategory>();
for (Ref<Subcategory> sc : this.subcategories) {
scs.add(sc.get());
}
return scs;
}
public void setSubcategory(Subcategory subcategory) {
this.subcategories.add(Ref.create(subcategory));
}
public Image getImage() {
if(image != null) {
return image.get();
}
return null;
}
public void setImage(Image image) {
this.image = Ref.create(image);
}
}
#Entity
public class Subcategory {
#Id
private Long id;
private String name;
private String description;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class CategoryDTO {
private Long id;
#NotNull
private String name;
private String description;
private List<Subcategory> subcategories = new ArrayList<Subcategory>();
private Long imageId;
public CategoryDTO() {
}
public CategoryDTO(Category category) {
this.id = category.getId();
this.name = category.getName();
this.description = category.getDescription();
this.subcategories = category.getSubcategories();
if (category.getImage() != null) {
this.imageId = category.getImage().getId();
}
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public List<Subcategory> getSubcategories() {
return subcategories;
}
public void setSubcategories(List<Subcategory> subcategories) {
this.subcategories = subcategories;
}
public Long getImageId() {
return imageId;
}
public void setImageId(Long imageId) {
this.imageId = imageId;
}
}
CategoryDAO
public class CategoryDAO {
private static final Logger log = Logger.getLogger(CategoryService.class.getName());
public static QueryResultIterator<Category> getCategories() {
QueryResultIterator<Category> categories = ofy().load().type(Category.class).iterator();
return categories;
}
}
public class SubcategoryDAO {
public static Subcategory createSubcategory(Long categoryId, Subcategory data) {
// save sub category
Subcategory subcategory = new Subcategory();
if (data.getName() != null) {
subcategory.setName(data.getName());
}
if (data.getDescription() != null) {
subcategory.setDescription(data.getDescription());
}
ofy().save().entity(subcategory).now();
Category category =
ofy().load().type(Category.class).id(categoryId).get();
category.setSubcategory(subcategory);
ofy().save().entity(category).now();
return subcategory;
}
}
CategoryService
#Path("/categories")
public class CategoryService {
#GET
#Produces(MediaType.APPLICATION_JSON)
public String getCategories() {
try {
List<CategoryDTO> categories = new ArrayList<CategoryDTO>();
QueryResultIterator<Category> cats = CategoryDAO.getCategories();
while (cats.hasNext()) {
categories.add(new CategoryDTO(cats.next()));
}
Map<String, List<CategoryDTO>> map = new HashMap<String, List<CategoryDTO>>();
map.put("categories", categories);
return Helper.prepareResponse(map);
} catch (Exception e) {
LogService.getLogger().severe(e.getMessage());
throw new WebApplicationException(500);
}
}
}
Problem:-
When i hit getCategories service, it is showing unexpected behaviour.Instead of showing all the subcategories, it is showing random no of different subcategories every time.
For example say,
first i save a category "c"
then i save subcategories "sa", "sb" and "sc"
On hitting getCategry service,
Expected Behaviour -
{
"status": 200,
"categories" : [{
"name":a,
"subcategories": [
{
"name":"sa"
},
{
"name":"sb"
},
{
"name":"sc"
}
]
}]
}
Outputs i get is something like this -
{
"status": 200,
"categories" : [{
"name":a,
"subcategories": [
{
"name":"sa"
},
{
"name":"sc"
}
]
}]
}
or
{
"status": 200,
"categories" : [{
"name":a,
"subcategories": [{
"name":"sb"
}]
}]
}
To summarize this question, you're performing a query (give list of all categories) and getting back inconsistent results.
This is the system working as advertised. Read this: https://cloud.google.com/appengine/docs/java/datastore/structuring_for_strong_consistency
Eventual consistency is something that you learn to live with and work around when you need it. There is no way to force a query to be strongly consistent without changing the structure of your data - say, put it under a single entity group - but that has repercussions as well. There is no free lunch if you want a globally replicated, infinitely-scalable database.
In addition to eventual consistency, the datastore has no defined ordering behavior if you do not specify a sort order in your query. So that might add to your confusion.
Welcome to the wonderful world of eventual consistency. When I encountered something like this, using ObjectifyService.begin() instead of ObjectifyService.ofy() resolved it. Unlike ofy(), begin() gets you fresh data every time.