Dynamodb Mapper Save functions not creating the item in table - java

I tried using the dynamodbmapper for crud operations over the table. When I am using the save functionality from the mapper code getting executed with out any error or exceptions but when I scan the table records were not reflecting what could be the possible error I am doing in below way
try{
User user = new User();
/* added some dummy data to user object*/
static AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
static DynamoDBMapper dynamoDB = new DynamoDBMapper(client, new DynamoDBMapperConfig(DynamoDBMapperConfig.SaveBehavior.CLOBBER));
dynamoDB.save(user);
}catch(Exception e){
}
My class object
#DynamoDBTable(tableName = "users")
public class User {
private String id;
private String user_id;
private String email;
private String name;
private String mobile_no;
private Integer createdDate;
private Integer modifiedDate;
#DynamoDBHashKey(attributeName = "id")
public String getId(){
return id;
}
public void setId(String id) {
this.id = id;
}
#DynamoDBAttribute(attributeName = "user_id")
public String getUser_id() {
return user_id;
}
public void setUser_id_ref(String user_id) {
this.user_id = user_id;
}
#DynamoDBAttribute(attributeName = "email")
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#DynamoDBAttribute(attributeName = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#DynamoDBAttribute(attributeName = "mobile_no")
public String getMobile_no() {
return mobile_no;
}
public void setMobile_no(String mobile_no) {
this.mobile_no = mobile_no;
}
#DynamoDBAttribute(attributeName = "created_date")
public Integer getCreatedDate() {
return createdDate;
}
public void setCreatedDate(Integer createdDate) {
this.createdDate = createdDate;
}
#DynamoDBAttribute(attributeName = "modified_date")
public Integer getModifiedDate() {
return modifiedDate;
}
public void setModifiedDate(Integer modifiedDate) {
this.modifiedDate = modifiedDate;
}
For scanning i have used the command
aws dynamodb scan --table-name users
Result for the above command is coming as below
{
"Items": [],
"Count": 0,
"ScannedCount": 0,
"ConsumedCapacity": null
}
Table Description
aws dynamodb describe-table --table-name users
{
"Table": {
"AttributeDefinitions": [
{
"AttributeName": "id",
"AttributeType": "S"
}
],
"TableName": "users",
"KeySchema": [
{
"AttributeName": "id",
"KeyType": "HASH"
}
],
"TableStatus": "ACTIVE",
"CreationDateTime": "2022-09-29T19:33:02.692000+05:30",
"ProvisionedThroughput": {
"LastDecreaseDateTime": "2022-09-29T19:45:29.763000+05:30",
"NumberOfDecreasesToday": 0,
"ReadCapacityUnits": 1,
"WriteCapacityUnits": 1
}
}
How ever I tried creating a test class where I just have hashkey attribute and tried saving the data it got persisted
package com.moneyview.model.dynamo;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAutoGeneratedKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable;
import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType;
#DynamoDBTable(tableName = "users")
public class UserTest {
private String id;
#DynamoDBHashKey(attributeName = "id")
public String getId(){
return id;
}
public void setId(String id) {
this.id = id;
}
}
test code for inserting
public void testinsertItem(){
try{
UserTest test = new UserTest();
test.setId("8a8180967e8b5112017e8b99268702df");
dynamoDB.save(test);
}catch (Exception e){
System.out.println("Something went wrong while inserting the records to DynamoDb");
}
}
When I tried scanning the table
aws dynamodb scan --table-name users
Result:
{
"Items": [
{
"id": {
"S": "8a8180967e8b5112017e8b99268702df"
}
}
],
"Count": 1,
"ScannedCount": 1,
"ConsumedCapacity": null
}
not sure where I am doing wrong or if there is any issue in the config please help me

The code which you shared is correct, and the item should be persisted.
However, you would need to show your full class, and confirm how you are checking the item exists?
You mention it doesn't exist when your Scan? Are you scanning from your code directly after writing? Check that you have made your Scan Strongly Consistent to ensure you get the latest value.
https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Scan.html#DDB-Scan-request-ConsistentRead
If this does not resolve the issue, I will be able to help you further when you share the rest of your code.
Reviewing your updated code it seems pretty fine, I did notice some issues with the setters you defined, but i'm not certain that is your issue. The below code snippet works for me:
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.datamodeling.*;
import java.util.List;
public class UserOverflow {
public static void main(String[] args){
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
DynamoDBMapper dynamoDB = new DynamoDBMapper(client, new DynamoDBMapperConfig(DynamoDBMapperConfig.SaveBehavior.CLOBBER));
User myUser = new User();
myUser.setId("1");
try{
dynamoDB.save(myUser);
}catch(Exception e){
System.out.println(e.getMessage());
}
DynamoDBScanExpression scanExpression = new DynamoDBScanExpression()
.withConsistentRead(Boolean.TRUE);
try{
List<User> scanResult = dynamoDB.scan(User.class, scanExpression);
for (User user : scanResult) {
System.out.println(user.getId());
}
}catch (Exception e){
System.out.println(e.getMessage());
}
}
#DynamoDBTable(tableName = "users")
public static class User {
private String id;
private String user_id;
private String email;
private String name;
private String mobile_no;
private Integer createdDate;
private Integer modifiedDate;
#DynamoDBHashKey(attributeName = "id")
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#DynamoDBAttribute(attributeName = "user_id")
public String getUserId() {
return user_id;
}
public void setUserId(String user_id) {
this.user_id = user_id;
}
#DynamoDBAttribute(attributeName = "email")
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#DynamoDBAttribute(attributeName = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#DynamoDBAttribute(attributeName = "mobile_no")
public String getMobileNo() {
return mobile_no;
}
public void setMobileNo(String mobile_no) {
this.mobile_no = mobile_no;
}
#DynamoDBAttribute(attributeName = "created_date")
public Integer getCreatedDate() {
return createdDate;
}
public void setCreatedDate(Integer createdDate) {
this.createdDate = createdDate;
}
#DynamoDBAttribute(attributeName = "modified_date")
public Integer getModifiedDate() {
return modifiedDate;
}
public void setModifiedDate(Integer modifiedDate) {
this.modifiedDate = modifiedDate;
}
}
}
I'm not sure if your did not have log statements inside your catch block but that is one thing you should definitely add. Should that fail, I would take a look at the following:
IAM policy, do you have the correct permissions
Internet access, does where you are executing the code from have a path to the DynamoDB endpoint?

Related

Unable to retrieve data from MySQL using Spring boot JPA

I am getting a java.lang.NullPointerException error at the line where the program begins to retrieve data from the database, specifically starting with the code recordDB.setAccountName(billing.getAccountId().getAccountName());. The entity tables are joined together and at first I thought that it can't retrieve data from other other tables but I tried to run with just recordDB.setAmount(billing.getAmount()); Can someone explain what I missed or is there something wrong with the logic?
Component
#Component
public class FileProcessor {
#Autowired
private BillingRepository billingRepository;
public FileProcessor() {
}
public List<Record> retrieveRecordfromDB(List<Request> requests) throws BarsException{
List<Record> records = new ArrayList<>();
if (!requests.isEmpty()) {
for (Request request : requests) {
Billing billing = billingRepository
.findByBillingCycleAndStartDateAndEndDate(
request.getBillingCycle()
, request.getStartDate()
, request.getEndDate());
if (billing == null) {
throw new BarsException(BarsException.NO_RECORDS_TO_WRITE);
}
Record recordDB = new Record();
recordDB.setBillingCycle(request.getBillingCycle());
recordDB.setStartDate(request.getStartDate());
recordDB.setEndDate(request.getStartDate());
recordDB.setAccountName(billing.getAccountId().getAccountName());
recordDB.setFirstName(billing.getAccountId().getCustomerId().getFirstName());
recordDB.setLastName(billing.getAccountId().getCustomerId().getLastName());
recordDB.setAmount(billing.getAmount());
records.add(recordDB);
}
}
return records;
}
}
Account Entity
#Entity
public class Account {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "account_id")
private int accountId;
private String accountName;
private LocalDateTime dateCreated;
private String isActive;
private String lastEdited;
public Account() {
}
public int getAccountId() {
return accountId;
}
public void setAccountId(int accountId) {
this.accountId = accountId;
}
public String getAccountName() {
return accountName;
}
public void setAccountName(String accountName) {
this.accountName = accountName;
}
public LocalDateTime getDateCreated() {
return dateCreated;
}
public void setDateCreated(LocalDateTime dateCreated) {
this.dateCreated = dateCreated;
}
public String getIsActive() {
return isActive;
}
public void setIsActive(String isActive) {
this.isActive = isActive;
}
public String getLastEdited() {
return lastEdited;
}
public void setLastEdited(String lastEdited) {
this.lastEdited = lastEdited;
}
public Customer getCustomerId() {
return customerId;
}
public void setCustomerId(Customer customerId) {
this.customerId = customerId;
}
public Set<Billing> getBilling() {
return billing;
}
public void setBilling(Set<Billing> billing) {
this.billing = billing;
}
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "customer_id")
private Customer customerId;
#OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name = "account_id")
private Set<Billing> billing;
}
Billing Entity
#Entity
public class Billing {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "billing_id")
private int billingId;
//private int billingId;
private int billingCycle;
private String billingMonth;
private Double amount;
private LocalDate startDate;
private LocalDate endDate;
private String lastEdited;
//private Account accountId;
public Billing() {
}
public int getBillingId() {
return billingId;
}
public void setBillingId(int billingId) {
this.billingId = billingId;
}
public int getBillingCycle() {
return billingCycle;
}
public void setBillingCycle(int billingCycle) {
this.billingCycle = billingCycle;
}
public String getBillingMonth() {
return billingMonth;
}
public void setBillingMonth(String billingMonth) {
this.billingMonth = billingMonth;
}
public Double getAmount() {
return amount;
}
public void setAmount(Double amount) {
this.amount = amount;
}
public LocalDate getStartDate() {
return startDate;
}
public void setStartDate(LocalDate startDate) {
this.startDate = startDate;
}
public LocalDate getEndDate() {
return endDate;
}
public void setEndDate(LocalDate endDate) {
this.endDate = endDate;
}
public String getLastEdited() {
return lastEdited;
}
public void setLastEdited(String lastEdited) {
this.lastEdited = lastEdited;
}
public Account getAccountId() {
return accountId;
}
public void setAccountId(Account accountId) {
this.accountId = accountId;
}
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "account_id")
private Account accountId;
}
Customer Entity
#Entity
public class Customer {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "customer_id")
private int customerId;
private String firstName;
private String lastName;
private String address;
private String status;
private LocalDateTime dateCreated;
private String lastEdited;
public Customer() {
}
public int getCustomerId() {
return customerId;
}
public void setCustomerId(int customerId) {
this.customerId = customerId;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public LocalDateTime getDateCreated() {
return dateCreated;
}
public void setDateCreated(LocalDateTime dateCreated) {
this.dateCreated = dateCreated;
}
public String getLastEdited() {
return lastEdited;
}
public void setLastEdited(String lastEdited) {
this.lastEdited = lastEdited;
}
#OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name = "customer_id")
private Set<Account> account;
}
Repository
#Repository
public interface BillingRepository extends JpaRepository<Billing, Integer> {
public Billing findByBillingCycleAndStartDateAndEndDate (int billingCycle, LocalDate startDate, LocalDate endDate);
}
Your naming is unintuitive, which hinders people unfamiliar with the code:
recordDB implies that it is the Database for records. Instead, it is a record that is to be saved in the DB. Naming it "RecordToSave" or similar is much better, since it gets the intention across.
getAccountId() implies that the id of an account is returned (an int or long) NOT that the account itself is returned. You should rename it to getAccount()
About the issue:
What you are using as a bidirectional ManyToOne <-> OneToMany relationship.
One side should be the owning side of the relationship. Here the #JoinColumn should be stated. The receiving end should have a MappedBy Property.
See this guide for more information: https://thorben-janssen.com/hibernate-tips-map-bidirectional-many-one-association/
It should solve the issue, since only the data retrieval for connected tables does not seem to work, hence fixing the references should fix the issue.
Your billing.getAmount() does refer to data written in the billing object/table, and is not from another table like billing.getAccountId().getAccountName() which gets data from the account table connected to the billings table.
Last, but not least:
Think about your cascading strategy. The way it currently works, deleting a billing will delete the account of that billing, which deletes all references made there and so on since you currently use Cascade.All for ALL entries. This is bad.
Here is a guide for cascading: https://howtodoinjava.com/hibernate/hibernate-jpa-cascade-types/
Are you sure the field names in the Billing class exactly match the database column names? I see you set the column name to "billing_id" explicitly for the id field, but not for any other fields. My guess is that the fields in that class are all null since there are no corresponding database columns (debug to confirm).

add a dynamic column to an entity without saving it to the table

I have a model class like the following:
package com.example.model;
import java.util.Map;
import javax.persistence.Column;
import javax.persistence.Convert;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import com.example.helpers.StringMapConverter;
#Entity
#Table(name = "buildingcompanies")
public class Buildcompanies {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#Column(name = "shortname")
private String shortname;
#Column(name = "fullname")
private String fullname;
#Column(name = "address")
private String address;
#Column(name = "telephone")
private String telephone;
#Column(name = "website")
private String website;
#Column(name = "sociallinks")
#Convert(converter = StringMapConverter.class)
private Map<String, String> sociallinks;
#Column(name = "foundationyear")
private String foundationyear;
public Buildcompanies() {
}
public Buildcompanies(String shortname, String fullname, String address, String telephone, String website,
Map<String, String> map, String foundationyear) {
this.shortname = shortname;
this.fullname = fullname;
this.address = address;
this.telephone = telephone;
this.website = website;
this.sociallinks = map;
this.foundationyear = foundationyear;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getShortname() {
return shortname;
}
public void setShortname(String shortname) {
this.shortname = shortname;
}
public String getFullname() {
return fullname;
}
public void setFullname(String fullname) {
this.fullname = fullname;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getTelephone() {
return telephone;
}
public void setTelephone(String telephone) {
this.telephone = telephone;
}
public String getWebsite() {
return website;
}
public void setWebsite(String website) {
this.website = website;
}
public Map<String, String> getSociallinks() {
return sociallinks;
}
public void setSociallinks(Map<String, String> sociallinks) {
this.sociallinks = sociallinks;
}
public String getFoundationyear() {
return foundationyear;
}
public void setFoundationyear(String foundationyear) {
this.foundationyear = foundationyear;
}
}
And the method in a controller to show the output:
public ResponseEntity<List<Buildcompanies>> getAllCompanies(#RequestParam(required = false) String name) {
try {
List<Buildcompanies> companies = new ArrayList<Buildcompanies>();
int test=0;
if (name == null)
{
buildcompaniesRepository.findAll().forEach(companies::add);
}
else
buildcompaniesRepository.findByShortnameContaining(name).forEach(companies::add);
if (companies.isEmpty()) {
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
return new ResponseEntity<>(companies, HttpStatus.OK);
} catch (Exception e) {
return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
It does show an output everythin is just fine:
[
{
"id": 81,
"shortname": "testing",
"fullname": "test",
"address": "addrtest",
"telephone": "380979379992",
"website": "www.site.com",
"sociallinks": {
"facebook": "fb.com"
},
"foundationyear": "1991"
}
]
And I want to calculate each companies rating while showing data to the end user. So the output should be as follows:
[
{
"id": 81,
"shortname": "testing",
"fullname": "test",
"address": "addrtest",
"telephone": "380979379992",
"website": "www.site.com",
"sociallinks": {
"facebook": "fb.com"
},
"foundationyear": "1991",
"rating": "1.5"
}
]
Is it posible to add the rating column dynamicly to the company list or I should to create rating column in database, update method for it in the controller, iterate over the findAll() results and call it each time user tryes to acces /list endpoint?
You have two options:
You may introduce a new attribute in the Buildcompanies class for the purpose and annotate it with #Transient.
This will denote that the attribute need not be persisted in the DB and JPA won't attempt to create a column in the table.
The recommended approach is to not use the Entity class as a response object. You should ideally have a domain object and the database response should be mapped to this object. While mapping you can apply whatever custom details you want to add to it.
Just add #Transient annotation to your dynamic field. There is no corresponding column required in the database. The value of the transient column exists only in runtime.
In general, it is a bad idea to share the entity as a JSON with an external system for many reasons. Use intermediate DTO instead. There are a lot of libraries that allow configurable auto-mapping from entity to DTO (ModelMapper is pretty good for me).

Pull Request Doesn't update repository

I am trying to change a Perfil object in PerfilRepository by sending the following request with the following code:
package br.com.bandtec.projetocaputeam.controller;
import br.com.bandtec.projetocaputeam.dominio.*;
import br.com.bandtec.projetocaputeam.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
#RestController
#RequestMapping("/caputeam")
public class CaputeamController {
//USER CLASS
public abstract class Perfil {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column(name = "nome")
#NotNull
#Size(min = 5,max = 30)
#Pattern(regexp = "^[a-zA-Z\s]*$", message = "Nome inválido! Digite apenas letras e espaçamento") //Permite apenas letras e espaço
private String nome;
#NotNull
#CPF
private String cpf;
#Column(name = "email")
#NotNull
#Email
private String email;
#NotNull
#Size(min = 5,max = 12)
private String senha;
private Integer telefone;
#DecimalMin("0")
#DecimalMax("5")
private Double avaliacao;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "id_endereco")
private Endereco endereco;
#NotNull
private String tipoPerfil;
#OneToOne(cascade = CascadeType.ALL)
private Categoria categoriaAutonomo;
//Getters
public Integer getId() {
return id;
}
public String getNome() {
return nome;
}
public String getCpf() {
return cpf;
}
public String getEmail() {
return email;
}
public String getSenha() {
return senha;
}
public Integer getTelefone() {
return telefone;
}
public Double getAvaliacao() {
return avaliacao;
}
public Endereco getEndereco() {
return endereco;
}
public String getTipoPerfil() {
return tipoPerfil;
}
public Categoria getCategoriaAutonomo() {
return categoriaAutonomo;
}
//Setters
public void setTipoPerfil(String tipoPerfil) {
this.tipoPerfil = tipoPerfil;
}
public void setNome(String nome) {
this.nome = nome;
}
public void setCpf(String cpf) {
this.cpf = cpf;
}
public void setEmail(String email) {
this.email = email;
}
public void setSenha(String senha) {
this.senha = senha;
}
public void setTelefone(Integer telefone) {
this.telefone = telefone;
}
public void setAvaliacao(Double avaliacao) {
this.avaliacao = avaliacao;
}
public void setEndereco(Endereco endereco) {
this.endereco = endereco;
}
public void setCategoriaAutonomo(Categoria categoriaAutonomo) {
this.categoriaAutonomo = categoriaAutonomo;
}
}
//--- REPOSITORIES
#Autowired
private PerfilService perfilService = new PerfilService();
//--- USUARIOS
#GetMapping("/usuarios")
public ResponseEntity getUsuario(){
return perfilService.getPerfisRepository();
}
#PostMapping("/cadastrar-usuario")
public ResponseEntity cadastrarUsuario(#RequestBody #Valid Perfil novoPerfil){
return perfilService.cadastrarUsuario(novoPerfil);
}
#PutMapping("/usuarios/{id}")
public ResponseEntity alterarUsuario(#RequestBody #Valid Perfil usuarioAlterado, #PathVariable int id){
return perfilService.alterarPerfil(usuarioAlterado,id);
}
And thats my method for changing my perfil object
public ResponseEntity alterarPerfil(Perfil perfilAlterado, int id){
perfisRepository.findById(id).map(perfil -> {
perfil.setNome(perfilAlterado.getNome());
perfil.setEmail(perfilAlterado.getEmail());
perfil.setTelefone(perfilAlterado.getTelefone());
return ResponseEntity.ok().build();
});
return ResponseEntity.badRequest().body("Alteração inválida!");
}
Im sending my put request in postman like that:
{
"id": 1,
"nome": "Beatriz Barros",
"cpf": "103.725.810-05",
"email": "bia#hotmail.com",
"senha": "121520",
"telefone": 1134577777,
"avaliacao": 4.9,
"endereco": {
"id": 1,
"cep": "03311111",
"bairro": "Vila Poeira",
"logradouro": "RuaFlor",
"numeroLogradouro": 7,
"complemento": null,
"uf": "sp",
"cidade": "SaoPaulo"
},
"tipoPerfil": "autonomo",
"categoriaAutonomo": {
"id": 1,
"nome": "Jardineiro",
"descricao": null
},
"precoAutonomo": 0.0
}
But it always returns status 400 bad request!
I already tried to send only the fields I want to change (name, email and phone) but it also didn't work
I also tried to send with and without the ID and nothing to work
How can I send a correct request?
Well, that's actually what you're doing.
perfisRepository.findById(id).map(perfil -> {
perfil.setNome(perfilAlterado.getNome());
perfil.setEmail(perfilAlterado.getEmail());
perfil.setTelefone(perfilAlterado.getTelefone());
return ResponseEntity.ok().build();
});
perfil -> { /* */ } is actually a lambda expression or in other words: an anonymous method. So instead of returning in the alterarPerfil method, you're returning in the anonymous method.
I've never worked with Spring, but from reading the docs, I assume that perfisRepository is implementing the CrudRepository interface.
The right code should be something like:
Perfil oldObject = perfisRepository.findById(id).get();
if(oldObject == null) return ResponseEntity.badRequest().body("Alteração inválida!");
oldObject.setNome(perfilAlterado.getNome());
oldObject.setEmail(perfilAlterado.getEmail());
/* and so on - you probably want to use reflection or a helping class to save you some time here */
// For a given entity, save will act as update too.
perfisRepository.save(oldObject);
return ResponseEntity.ok().build();
Since in your code, you aren't persisting any change.

Why do i get wrong object property from server?

When I get List from server with spring I get in client object user like this:
{
"id": 1,
"name": "hgfhj",
"age": 120,
"createdDate": 1457211138000,
"admin": true
}
UserController.java method:
#RequestMapping(value = "/user/", method = RequestMethod.GET)
public ResponseEntity<List<User>> getList() {
List usersList = userService.getList();
ResponseEntity<List<User>> respEntity = null;
if(usersList.isEmpty()){
respEntity =new ResponseEntity<List<User>>(HttpStatus.NO_CONTENT);
return respEntity;
}
respEntity =new ResponseEntity<List<User>>(usersList, HttpStatus.OK);
return respEntity;
}
And when I use Gson I get in client object user like this:
{
"id": 1,
"name": "hgfhj",
"age": 120,
"isAdmin": true,
"createdDate": "Mar 5, 2016 10:52:18 PM"
}
UserController.java method:
#RequestMapping(value = "/user/", method = RequestMethod.GET)
public String getList() {
List usersList = userService.getList();
ResponseEntity<List<User>> respEntity = null;
respEntity =new ResponseEntity<List<User>>(usersList, HttpStatus.OK);
Gson gson = new Gson();
String json = gson.toJson(usersList);
return json;
}
In all project user property name "isAdmin", I do not understand why it's changed to "admin". How can I use spring but get in client "isAdmin" without gson?
User.java:
#Entity
public class User {
/*#Column(name="id")*/
#Id
#GeneratedValue
private int id;
#Column(name="name")
private String name;
#Column(name="age")
private int age;
#Column(name="isAdmin")
private boolean isAdmin;
#Column(name="createdDate")
#Temporal(TemporalType.TIMESTAMP)
#DateTimeFormat(pattern = "dd.MM.yyyy")
private Date createdDate;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public boolean isAdmin() {
return isAdmin;
}
public Date getCreatedDate() {
return createdDate;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setIsAdmin(boolean isAdmin) {
this.isAdmin = isAdmin;
}
public void setCreatedDate(Date createdDate) {
this.createdDate = createdDate;
}
}
please do following changes into your User class's setter method,
#JsonProperty("isAdmin") // i guess you want isAdmin into response..
public void setIsAdmin(boolean isAdmin) {
this.isAdmin = isAdmin;
}
Annotate your User objects attributes with #JsonProperty to spesify the name you want as output.
Example
public class User {
...
#SerializedName("isAdmin")
#Column(name="isAdmin")
private boolean admin;
...
}
this will return something like
{
"isAdmin" : true
}
for more information: http://www.javacreed.com/gson-annotations-example/
Updated:
For future reference #JsonProperty("name") needs to be on the getters with gson, not the attributes.

hibernate gives two rows the same instead of two distinct rows

I have a user dao
#Entity
#Table(name="EBIGUSERTIM")
public class EbigUser {
private String id;
private Integer source;
private String entryscheme;
private String fullName;
private String email;
private Long flags;
private String status;
private String createdBy;
private Date createdStamp;
private String modifiedBy;
private Date modifiedStamp;
#Id
#Column(name="ID")
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#Id
#Column(name="SOURCE")
public Integer getSource() {
return source;
}
public void setSource(Integer source) {
this.source = source;
}
#Column(name="ENTRYSCHEME")
public String getEntryscheme() {
return entryscheme;
}
public void setEntryscheme(String entryscheme) {
this.entryscheme = entryscheme;
}
#Column(name="FULLNAME")
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
#Column(name="EMAIL")
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#Column(name="FLAGS")
public Long getFlags() {
return flags;
}
public void setFlags(Long flags) {
this.flags = flags;
}
#Column(name="STATUS")
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
#Column(name="CREATEDBY")
public String getCreatedBy() {
return createdBy;
}
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
#Column(name="CREATEDSTAMP")
public Date getCreatedStamp() {
return createdStamp;
}
public void setCreatedStamp(Date createdStamp) {
this.createdStamp = createdStamp;
}
#Column(name="MODIFIEDBY")
public String getModifiedBy() {
return modifiedBy;
}
public void setModifiedBy(String modifiedBy) {
this.modifiedBy = modifiedBy;
}
#Column(name="MODIFIEDSTAMP")
public Date getModifiedStamp() {
return modifiedStamp;
}
public void setModifiedStamp(Date modifiedStamp) {
this.modifiedStamp = modifiedStamp;
}
i am selecting 2 rows out of the db. The sql works
select * from ebigusertim where id='blah'
It returns 2 distinct rows. When i query the data using hibernate, it appears that the object memory is not being allocated for each entry in the list. Thus, i get 2 entries in the list with the same object.
Criteria userCriteria = session.createCriteria(EbigUser.class);
userCriteria.add(Restrictions.eq("id", id));
userlist = userCriteria.list();
Why are you defining two id columns(both id and source are mapped with annotation #Id)?
#Id
#Column(name="ID")
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#Id
#Column(name="SOURCE")
public Integer getSource() {
return source;
}
Please remove one if it is by mistake. If both together make composite key, map them accordingly e.g.
#Embeddable
public class UserPK implements Serializable {
#Column(name = "ID", nullable = false)
private String id;
#Column(name = "SOURCE", nullable = false)
private Integer source;
.....
.....
}
Use this new class in you original class as Id as below:
#EmbeddedId
private UserPK userPK;
Hope this helps.

Categories