Conditional update in Dynamo Db using mapper - java

I am trying to do a conditional update on a field Score in my table based on the condition that marks to be updated are greater than the current score.
I have written following code ,
StudentDO temp = mapper.load(StudentDO.class, student.getId());
temp.setScore(marks);
ArrayList<AttributeValue> list = new ArrayList<AttributeValue>();
list.add(new AttributeValue().withN(Oldmarks.toString()));
Map<String,ExpectedAttributeValue> expectedAttributes = new
HashMap<String,ExpectedAttributeValue>();
ExpectedAttributeValue expectedAttributeValue = new
ExpectedAttributeValue().withAttributeValueList(list)
.withComparisonOperator("GT");
expectedAttributes.put("Score",expectedAttributeValue);
mapper.save(temp, new DynamoDBSaveExpression().withExpected(expectedAttributes));
This is failing with this runtime exception
com.amazonaws.services.dynamodbv2.model.ConditionalCheckFailedException: The conditional request failed (Service: null; Status Code: 400; Error Code: ConditionalCheckFailedException; Request ID: null)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.amazonaws.services.dynamodbv2.local.embedded.DDBExceptionMappingInvocationHandler.handleDynamoDBLocalServiceException(DDBExceptionMappingInvocationHandler.java:87)
at com.amazonaws.services.dynamodbv2.local.embedded.DDBExceptionMappingInvocationHandler.invoke(DDBExceptionMappingInvocationHandler.java:66)
at com.sun.proxy.$Proxy19.updateItem(Unknown Source)
at com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper$SaveObjectHandler.doUpdateItem(DynamoDBMapper.java:854)
at com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper$2.executeLowLevelRequest(DynamoDBMapper.java:594)
at com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper$SaveObjectHandler.execute(DynamoDBMapper.java:733)
at com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper.save(DynamoDBMapper.java:623)
at com.amazonaws.services.dynamodbv2.datamodeling.AbstractDynamoDBMapper.save(AbstractDynamoDBMapper.java:128)
I am not able to debug why is it throwing Conditional Check Failed Exception.
I could make out the request is not properly formed , but not sure where is it malformed ?
I have tried to align it to these docs
http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodbv2/datamodeling/DynamoDBSaveExpression.html
http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodbv2/model/ExpectedAttributeValue.html
http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodbv2/model/AttributeValue.html
My DB schema is this
#DynamoDBTable(tableName = "Student")
public class StudentDO {
#DynamoDBHashKey(attributeName = "Id")
private Integer id;
#DynamoDBAttribute(attributeName = "Name")
private String name;
#DynamoDBAttribute(attributeName = "Score")
private Integer score;
#Override
public String toString() {
return "Student [Name=" + name + ", id=" + id + ", score=" + score + "]";
}
}

Each DynamoDB attribute must have a public getter and setter, since DynamoDBMapper works on JavaBeans (a class with a no argument constructor, and getters + setters for each private var). Modify your class to this:
#DynamoDBTable(tableName = "Student")
public class StudentDO {
private Integer id;
private String name;
private Integer score;
#DynamoDBAttribute(attributeName = "Id")
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#DynamoDBAttribute(attributeName = "Name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#DynamoDBAttribute(attributeName = "Score")
public Integer getScore() {
return score;
}
public void setScore(Integer score) {
this.score = score;
}
#Override
public String toString() {
return "Student [Name=" + name + ", id=" + id + ", score=" + score + "]";
}
}

Related

Passing a class object as a parameter in Postman

i am developing an API application, however I am having difficulties with a particular method.
The getCertificationPOJO method, is responsible for taking in a Store as a parameter and searching if that store exists in the database.
Now the problem here is how do I pass a Store object as a parameter in Postman. I have tried passing it in as a JSON string, but that is not working.
Apologies for the bad edit
Certification Controller
#Controller
public class CertController {
#Autowired
private CertificationRepository certRepo;
#Autowired
private StoreRepository StoreRepository;
#GetMapping(value = "/getCertObject")
public #ResponseBody
Optional<Certification> getCertificationPOJO(#RequestParam Store store)
{return Lists.newArrayList(certRepo.findAll()).stream().filter(e->e.getStore() == store).findFirst();}
}
Store Class
#Entity
#Table(name = "store")
public class Store implements com.halal.abstractions.Entity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#JsonIgnore
#OneToOne(optional = true) // By default this is set to true so technically this is redundant but, yea lets
// just keep it there
private Certification certification;
#NotNull
#Column(nullable = false)
private String name;
private String phoneNumber;
#NotNull
#Column(nullable = false)
private String address;
#NotNull
#Column(nullable = false)
private double latitude;
#NotNull
#Column(nullable = false)
private double longitude;
#NotNull
#Column(nullable = false)
private Date dateAdded;
static final DateFormat DF = new SimpleDateFormat("dd/MM/yyyy");
protected Store() {
}
public Store(String name, String phoneNumber, String address, double latitude, double longitude) {
this.name = name;
this.setPhoneNumber(phoneNumber);
this.setAddress(address);
this.latitude = latitude;
this.longitude = longitude;
this.dateAdded = new Date(System.currentTimeMillis());
}
#Override
public Long getId() {
return this.id;
}
#Override
public void setId(long id) {
this.id = id;
}
#Override
public String getName() {
return name;
}
#Override
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public Double getLatitude() {
return this.latitude;
}
public void setLatitude(double latitude) {
this.latitude = latitude;
}
public Double getLongitude() {
return this.longitude;
}
public void setLongitude(double longitude) {
this.longitude = longitude;
}
#Override
public String getDateAdded() {
return DF.format(dateAdded);
}
#Override
public void setCertification(Certification certification) {
this.certification = certification;
}
#Override
public Certification getCertification() {
return this.certification;
}
#Override
public String toString() {
return "Store{" + "id=" + id + ", certification=" + certification + ", name='" + name + '\'' + ", phoneNumber='"
+ phoneNumber + '\'' + ", address='" + address + '\'' + ", latitude=" + latitude + ", longitude="
+ longitude + ", dateAdded=" + dateAdded + '}';
}
}
Certification Class
#Entity
#Table(name = "certification")
public class Certification {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#NotNull
#Column(nullable = false)
private boolean isCertified;
#OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name = "id")
#JsonIgnore
private Store store;
public Certification() {
}
public long getId() {
return this.id;
}
public void setId(long id) {
this.id = id;
}
public Store getStore() {
return this.store;
}
public void setStore(Store store) {
this.store = store;
}
public boolean isIsCertified() {
return this.isCertified;
}
public void setIsCertified(boolean isCertified) {
this.isCertified = isCertified;
}
#Override
public String toString() {
return "Certification{" + "id=" + id + ", isCertified= " + isCertified + '}';
}
}
I would advise against sending a body in a GET request, see similar answer here
The query param route that #Murilo suggests is one way but if the way of determining whether a getCertificationPOJO already exists in the database depends solely on the id then you may only need to send the id in which case a path variable would be best like below where {id} can be replaced with the actual ID
GET /getCertObject/{id}
and then in the controller
#GetMapping("/getCertObject/{id}")
#ResponseBody
Optional<Certification> getCertificationPOJO(#PathVariable String id) {
...
}
You don't use Params section in this case. You use Body. Click on that tab and put your JSON OBJECT in the textbox that will appear. You also need to set CONTENT TYPE to JSON by selecting the proper value in the COMBO that appears farthest to the right of the attached image.
Check this out:
If you are using queryParams you have to pass individually each key/param, in your Postman you fill like it:
key: id value: 1
key: name value "asdasd"
key: phoneNumber value: "000"
(...)
Another option is you change your strategy and pass the entire json in your Body, but you will have to change your RestController to receive a #RequestBody instead of #RequestParam

Hibernate doesn't show the values of arraylist correctly [duplicate]

This question already has answers here:
How do I print my Java object without getting "SomeType#2f92e0f4"?
(13 answers)
Closed 2 years ago.
I am studying onetomany in hibernate I have an Instructor that has more than one course.I am using Instructor and Course class for Annotating my tables with the same names in the database.in the GetInstructorCourseDemo am trying to print the Instructor information with an associated course but inSystem.out.println("Course "+tempinstructor.getCourse()); what I see in the console is Course [MyHibernate.Course#56ccd751, MyHibernate.Course#458544e0] . it seems to me hibernate can read courses from database but it can't show it correctly otherwise have i no idea what can cause this problem
#Entity
#Table(name = "instructor")
public class Instructor {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#Column(name ="first_name" )
private String first_name;
#Column(name = "last_name")
private String last_name;
#Column(name = "email")
private String email;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "instructor_detail_id")
private instructor_detail Instructor_detail;
Instructor(){}
#OneToMany(mappedBy = "instructor",cascade = {CascadeType.DETACH,CascadeType.MERGE,CascadeType.PERSIST,
CascadeType.REFRESH})
private List<Course> course;
public Instructor(String first_name, String last_name, String email) {
this.first_name = first_name;
this.last_name = last_name;
this.email = email;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirst_name() {
return first_name;
}
public void setFirst_name(String first_name) {
this.first_name = first_name;
}
public String getLast_name() {
return last_name;
}
public void setLast_name(String last_name) {
this.last_name = last_name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public instructor_detail getInstructor_detail() {
return Instructor_detail;
}
public void setInstructor_detail(instructor_detail instructor_detail) {
Instructor_detail = instructor_detail;
}
public List<Course> getCourse() {
return course ;
}
public void setCourse(List<Course> course) {
this.course = course;
}
public void add(Course tempciurse){
if(course==null){
course=new ArrayList<>();
}
course.add(tempciurse);
tempciurse.setInstructor(this);
}
public class GetInstructorCourseDemo {
public static void main(String[]args) {
// create session factory
SessionFactory factory = new Configuration()
.configure("hibername.cfg.xml")
.addAnnotatedClass(Instructor.class)
.addAnnotatedClass(instructor_detail.class)
.addAnnotatedClass(Course.class)
.buildSessionFactory();
Session session = factory.getCurrentSession();
try {
session.beginTransaction();
int id=2;
Instructor tempinstructor=session.get(Instructor.class,id);
System.out.println("instructor : "+tempinstructor);
System.out.println("Course "+tempinstructor.getCourse());
session.getTransaction().commit();
System.out.println("Done!");
}
finally {
factory.close();
}
}
}
#Entity
#Table(name = "course")
public class Course {
#Id#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#Column(name = "title")
private String title;
#ManyToOne(cascade = {CascadeType.DETACH,CascadeType.REFRESH,CascadeType.MERGE,CascadeType.PERSIST})
#JoinColumn(name = "instructor_id")
private Instructor instructor;
Course(){}
public Course(String title) {
this.title = title;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Instructor getInstructor() {
return instructor;
}
public void setInstructor(Instructor instructor) {
this.instructor = instructor;
}
}
It missed toString() implementation in Instructor and Course types.
As you don't override it the default one is used -->
public String toString() {
return getClass().getName() + "#" + Integer.toHexString(hashCode());
}
NB : take care to not use course and instructor references directly in toString implementation causing a circular reference and so a StackOverflow error.
for solving this issue i have to add toString method in Course, Instructor as following
for Instructor
#Override
public String toString() {
return "Instructor{" +
"id=" + id +
", first_name='" + first_name + '\'' +
", last_name='" + last_name + '\'' +
", email='" + email + '\'' +
", Instructor_detail=" + Instructor_detail +
", course=" + course +
'}';
}
for Course
#Override
public String toString() {
return "Course{" +
"id=" + id +
", title='" + title + '\'' +
'}';
}
what was causing this confusion was that I didn't have toString method and I shouldn't have Instructor filed in my toString method

How to handle message error in Entity when using #MockMvc

I using #MockMvc test in spring controller but i have a question.
How to handle message error when MockMvc test not pass method.
Entity:
#Entity
#ApiModel(description = "All details about the Product")
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.AUTO,generator = "system-uuid")
#GenericGenerator(name = "system-uuid",strategy = "uuid2")
private String id;
#NotNull(message = "name can not null")
#ApiModelProperty(notes = "The name is product")
private String name;
#ApiModelProperty(notes = "The type is product")
private String type;
#NotNull(message = "category can not null")
private String category;
private String description;
private Double prince;
public Product() {
}
public Product(String name, String type, String category, String description, Double prince) {
this.name = name;
this.type = type;
this.category = category;
this.description = description;
this.prince = prince;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Double getPrince() {
return prince;
}
public void setPrince(Double prince) {
this.prince = prince;
}
#Override
public String toString() {
return "Product{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", type='" + type + '\'' +
", category='" + category + '\'' +
", description='" + description + '\'' +
", prince=" + prince +
'}';
}
}
StudentController:
#RestController
#RequestMapping("/products")
public class ProductController {
#PostMapping
public ResponseEntity<ProductDto> createProduct(#RequestBody Product product) {
URI location = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}").buildAndExpand(product.getId()).toUri();
return ResponseEntity.created(location).body(productService.createProduct(product));
}
}
In above entity, I want using #MockMvc test createProduct. If name in product is null, i want show message in #MockMvc . It look like: "name can not null" . If pass, i don't want show it. Bellow my test:
#Test
public void givenProductURIWithPost_whenMockMVC_thenVerifyResponse() {
this.mockMvc.perform(post("/products")).andDo(print())
.andExpect(status().isOk()).andExpect(content()
.contentType("application/json;charset=UTF-8"))
}
I have two question:
1.How to show message "name can not null" if name in product is
null in #mockmvc.
2. If my project in 20 field in Products entity : Example: name,category.. I can test sequence field in Products or only test
one time contain all field.

OnetoOne unknown mappedBy

I am getting a mappedBy unknown error between the relatioships of the following two entities.
It is a one to one relationship and the owner of the relationship should be the Story entity. I can't see my mistake in this code.
Both entities have getters and setters.
This is the first entity:
#Entity
#Table(name = "story")
public class Story {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String name;
private String link;
#OneToOne(mappedBy = "story", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private DesignTechnique designTechnique;
public Story(){
}
public Story(String name, String link){
this.name = name;
this.link= link;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link= link;
}
public DesignTechnique getDesignTechnique() {
return designTechnique;
}
public void setDesignTechnique(DesignTechnique designTechnique) {
this.designTechnique = designTechnique;
}
#Override
public String toString() {
return "UserStory{" +
"id=" + id +
", name='" + name + '\'' +
", link='" + link+ '\'' +
", designTechnique='" + designTechnique + '\'' +
'}';
}
}
This is the second entity:
#Entity
#Table(name = "designTechnique")
public class DesignTechnique {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String technique;
#OneToOne
#JoinColumn(name = "story_ID")
private Story story;
public DesignTechnique(){
}
public DesignTechnique(String technique){
this.technique = technique;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTechnique() {
return technique;
}
public void setTechnique(String technique) {
this.technique = technique;
}
public Story getStory() {
return story;
}
public void setStory(Story story) {
this.story = story;
}
#Override
public String toString() {
return "TestdesignTechnique{" +
"id=" + id +
", technique='" + technique + '\'' +
", story='" + story+ '\'' +
'}';
}
}
EDIT
Stacktrace:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: Unknown mappedBy in: com.clusters.Model.Story.designTechnique, referenced property unknown: com.clusters.Model.DesignTechnique.story
EDIT 2
I tried adding #PrimaryKeyJoinColumn instead of #JoinColumn in Design Entity, getting same error.
I have generated the getters and setters in both entities. So no typo's in these things.
It could be a hibernate bug !! see this :
https://hibernate.atlassian.net/browse/HHH-5695
Try to change the version of hibernate that you use.

java - Hibernate doesn't read object from database correctly

I am having some issues according Hibernate.
I have a more or less complex object structure that I want to save / load using the Hibernate EntityManager (version 4.3.5.Final). I managed to save it, but if I attempt to read the obejct, only the PK will be read. The EntityManager's find method returns null even with the correct PK so I am using its getReference method.
I still have troubles using the correct relationship (ManyToOne and such) so I most likely made a mistake there and I guess that is causing the problem.
Anyways.
My question is: How do i persist an object structure like this using Hibernate?
Here are the POJOs i am using:
EDIT: Updated the Code
CalculationList:
#Entity(name = "calculation")
public class CalculationList implements EntityList {
#Id
private Date created;
#OneToMany(mappedBy = "", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<Product> products;
public CalculationList(Date created) {
this.created = created;
this.products = new LinkedList<>();
}
public CalculationList(Date created, List<Product> products) {
this.created = created;
this.products = products;
}
public CalculationList() {
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
public List<Product> getProducts() {
return products;
}
public void setProducts(List<Product> entities) {
this.products = entities;
}
#Override
public String toString() {
return "CalculationList{" +
"created=" + created +
", products=" + products +
'}';
}
}
CalulatorEntity:
#Entity(name = "calculator_entity")
public class CalculatorEntity implements Serializable {
#Id
private int id;
private CalculatorEntityType type;
private String name;
private int number;
#ManyToOne(cascade = CascadeType.ALL)
private Product product;
public CalculatorEntity(CalculatorEntityType type) {
this.type = type;
}
protected CalculatorEntity() {
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public CalculatorEntityType getType() {
return type;
}
public void setType(CalculatorEntityType type) {
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public enum CalculatorEntityType {
GAS_PUMP, DELIVERY_BILL;
}
#Override
public String toString() {
return "CalculatorEntity{" +
"id=" + id +
", type=" + type +
", name='" + name + '\'' +
", product=" + product +
", number=" + number +
'}';
}
}
Product:
#Entity(name = "product")
public class Product implements Serializable {
#Id
private int id;
private String name;
private ProductType type;
#OneToMany(mappedBy = "product", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<CalculatorEntity> entities;
public Product(String name, ProductType type) {
this.name = name;
this.type = type;
this.entities = new LinkedList<>();
}
/**
* JPA - Konstruktor
*/
public Product() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ProductType getType() {
return type;
}
public void setType(ProductType type) {
this.type = type;
}
public List<CalculatorEntity> getEntities() {
return entities;
}
public void setEntities(List<CalculatorEntity> entities) {
this.entities = entities;
}
#Override
public String toString() {
return "Product{" +
"id=" + id +
", name='" + name + '\'' +
", type=" + type +
", entities=" + entities +
'}';
}
public enum ProductType {
FUEL("Treibstoff"), OIL("Öl"), OTHER("Verschiedenes");
private String name;
private ProductType(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
}
You are using the #OneToMany mapping with the wrong entity, instead of mapping Product class you are mapping CalculationList class, move the following configuration:
#OneToMany(mappedBy = "product", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<CalculatorEntity> entities;
to the Product class.

Categories

Resources