Spring data couchbase return null on one field - spring

I want to do a simple getAll, but I have a null value on an embedded object.
Response :
[
{
"id": "0da716f2-6ef0-404f-9403-4d869a6b6853",
"channelName": "general",
"broadcast": {
"tenantId": "45bd5d1f-f585-44df-b37c-7882c123a492",
"broadcastName": "fix",
"id": null
}
}
]
I cant get the broadcastId, in couchbase web I can see that its present there but I cannot get it when using getAll() nor any other method.
Classes :
#Document
//lombok...
public class Broadcast implements Serializable {
private static final long serialVersionUID = 1L;
#GeneratedValue(strategy = GenerationStrategy.UNIQUE)
//#JsonProperty(access = JsonProperty.Access.READ_ONLY)
//#Schema(accessMode = Schema.AccessMode.READ_ONLY)
private String id;
#Field
private String tenantId;
#Field
private String broadcastName;
}
#Document
//lombok...
public class Channel implements Serializable {
private static final long serialVersionUID = 1L;
#GeneratedValue(strategy = GenerationStrategy.UNIQUE)
private String id;
#Field
private String channelName;
#Field
private Broadcast broadcast;
}

Related

Spring JPA - How can I make JpaRepository queries using an #Embedded property?

I'm trying to make a existsBy query using a property that comes from an embedded class, but I'm receiving "No property 'cpf' found for type 'Patient'".
The class Patient uses the Person class as embedded.
Person.java
#Embeddable
#Data
public class Person {
#Column(nullable = false, length = 11)
private String cpf;
#Column(name = "full_name", nullable = false, length = 60)
private String fullName;
#Column(nullable = false)
private String birthdate;
#Column(name = "email", nullable = true, length = 30)
private String emailAddress;
#Column(name = "cellphone_number", nullable = true, length = 11)
private String cellphoneNumber;
}
Patient.java
#Data
#Entity
#Table(name = "tb_patient")
public class Patient implements Serializable {
#Serial
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "patient_id")
private UUID id;
#Column
private LocalDateTime registrationDate;
#Embedded
private Person Person;
}
PatientController.java (part of)
#PostMapping
public ResponseEntity<Object> savePatient(#RequestBody Person person) {
if(patientService.existsByCpf(person.getCpf())) {
return ResponseEntity.status(HttpStatus.CONFLICT).body("CONFLICT: CPF number is already in use!");
}
var patientModel = new Patient();
BeanUtils.copyProperties(person, patientModel);
patientModel.setRegistrationDate(LocalDateTime.now(ZoneId.of("UTC")));
return ResponseEntity.status(HttpStatus.CREATED).body(patientService.save(patientModel));
}
PatientService.java (part of)
#Service
public class PatientService {
final PatientRepository patientRepository;
public PatientService(PatientRepository patientRepository) {
this.patientRepository = patientRepository;
}
public boolean existsByCpf(String cpf) {
return patientRepository.existsByCpf((cpf));
}
PatientRepository.java
#Repository
public interface PatientRepository extends JpaRepository<Patient, UUID> {
boolean existsByCpf(String cpf);
}
How can I pass the #Embedded properties to the #Repository?
You can try separate by _ embedded filed name and it's filed.
#Repository
public interface PatientRepository extends JpaRepository<Patient, UUID> {
boolean existsByPerson_Cpf(String cpf);
}

Persisting data with JPA with existing datas

I want to persist an object like this one :
{
"paymentMode": "CREDIT CARD",
"totalAmount": 158.0,
"orderProducts": [
{
"productKeyId": "HycaR7sPeecIMZEewanuK0jzPo7S33",
"name": "Cornish crab salad, brown crab mayonnaise, toasted muffin",
"price": 20.0,
"qty": 1,
"imgPath": "pathImage",
"category": {
"categoryKeyId": "23ume70Fu6yqyGUWfQkW110P4ko3gZ",
"name": "Starter"
}
},...
],
"seller": {
"userKeyId": "qmNR5g2TD8Ja5KvA1DCQWzYj55nvbP",
"firstName": "David",
"lastName": "Vera",
"email": "david.vera#9online.fr",
"addresses": [
{
"addressKeyId": "2t7x0bFgP5B9Qb2ymnLL5aPZVwMFhJ",
"city": "Vancouver",
"country": "Canada",
"streetName": "123 street name",
"postalCode": "ABCCBA",
"type": "billing",
},...
]
},
"createdAt": "2019-10-22T09:48:06.000+0000"
}
Some object are already stored in Database such as seller, addresses, products and product category.
I created : Orders tables
#Entity
#Table(name="orders")
#Getter #Setter
public class OrderEntity implements Serializable {
#Getter(AccessLevel.NONE)
#Setter(AccessLevel.NONE)
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
private Long id;
#Column(nullable = false, unique = true)
private String orderKeyId;
// A sale belong to one seller
#ManyToOne(fetch = FetchType.LAZY)
private UserEntity seller;
private String paymentMode;
private double totalAmount;
#OneToMany(mappedBy = "pk.order")
#Valid
private List<OrderProductEntity> orderProducts;
}
An order_product table (pivot table):
#Entity
#Table(name="order_product")
#Getter #Setter
public class OrderProductEntity {
#EmbeddedId
#JsonIgnore
private OrderProductPK pk;
#Column(nullable = false)
private Integer qty;
// default constructor
public OrderProductEntity() {
super();
}
public OrderProductEntity(OrderEntity order, ProductEntity product, Integer quantity) {
pk = new OrderProductPK();
pk.setOrder(order);
pk.setProduct(product);
this.qty = quantity;
}
#Transient
public ProductEntity getProduct() {
return this.pk.getProduct();
}
...
}
And a product table
#Entity
#Table(name="products")
#Getter #Setter
public class ProductEntity implements Serializable {
#Getter(AccessLevel.NONE)
#Setter(AccessLevel.NONE)
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
private Long id;
#Column(nullable = false)
private String productKeyId;
// many to one relationship with category
#ManyToOne
#JoinColumn(name = "category_id")
private CategoryEntity category;
#Column(nullable = false)
private String name;
#Column(nullable = false)
private double price;
#Column(nullable = false)
private int qty;
private String imgPath;
#JsonManagedReference
#OneToMany(mappedBy = "pk.product", fetch = FetchType.EAGER)
#Valid
private List<OrderProductEntity> orderProducts;
}
The userEntity class :
#Entity
#Table(name = "users")
#Getter #Setter
public class UserEntity implements Serializable {
#Getter(AccessLevel.NONE)
#Setter(AccessLevel.NONE)
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
private Long id;
#Column(nullable = false, unique = true)
private String userKeyId;
#Column(nullable = false, length = 50)
private String firstName;
#Column(nullable = false, length = 50)
private String lastName;
#Column(nullable = false, length = 120, unique = true)
private String email;
#Column(nullable = false)
private String encryptedPassword;
private String emailVerificationToken;
// column definition do not work for all database engine. So set the value to false is the same
// #Column(nullable = false, columnDefinition = "boolean default false")
#Column(nullable = false)
private Boolean emailVerificationStatus = false;
// One user can have Many Addresses
#OneToMany(mappedBy = "userDetails", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JsonManagedReference
private List<AddressEntity> addresses;
}
And finally the embedded class :
#Embeddable
#Getter #Setter
#ToString
public class OrderProductPK implements Serializable {
private static final long serialVersionUID = 476151177562655457L;
#ManyToOne(optional = false, fetch = FetchType.LAZY)
#JoinColumn(name = "order_id")
private OrderEntity order;
#ManyToOne(optional = false, fetch = FetchType.LAZY)
#JoinColumn(name = "product_id")
private ProductEntity product;
...
}
I created a controller method to persist orders in a MySQL database:
public OrderRest createOrder(#RequestBody OrderRequestModel orderRequestModel) throws Exception {
OrderRest returnValue = new OrderRest();
ModelMapper modelMapper = new ModelMapper();
OrderDto orderDto = modelMapper.map(orderRequestModel, OrderDto.class);
OrderDto createdOrder = orderService.createOrder(orderDto);
returnValue = modelMapper.map(createdOrder, OrderRest.class);
// 5. Return the expected object
return returnValue;
}
I have an orderDTO object that contains several fields (including ID).
public class OrderDto implements Serializable {
#Getter(AccessLevel.NONE)
#Setter(AccessLevel.NONE)
private static final long serialVersionUID = 1L;
private Long id;
private String orderKeyId;
private String paymentMode;
private double totalAmount;
private List<ProductDto> orderProducts;
private UserDto seller;
private Date createdAt;
}
My productDTO object
public class ProductDto implements Serializable {
// ommit this member and do not generate getter / setter
#Getter(AccessLevel.NONE)
#Setter(AccessLevel.NONE)
private static final long serialVersionUID = 1L;
private Long id;
private String productKeyId;
private String name;
private double price;
private int qty;
private String imgPath;
private CategoryDto category = new CategoryDto();
}
The UserDto :
#Getter #Setter
#ToString
public class UserDto implements Serializable {
// ommit this member and do not generate getter / setter
#Getter(AccessLevel.NONE)
#Setter(AccessLevel.NONE)
private static final long serialVersionUID = 1L;
private long id;
private String userKeyId;
private String firstName;
private String lastName;
private String email;
private String password;
private String encryptedPassword;
private String emailVerificationToken;
private Boolean emailVerificationStatus = false;
private List<AddressDto> addresses;
// private List<RoleDto> roles;
}
the controller is calling my service layer :
#Override
public OrderDto createOrder(OrderDto orderDto) {
// create a new order
ModelMapper modelMapper = new ModelMapper();
OrderEntity orderEntity = modelMapper.map(orderDto, OrderEntity.class);
String orderKeyId = utils.generateOrderKeyId(30);
orderEntity.setOrderKeyId(orderKeyId);
orderEntity.setCreatedAt(orderDto.getCreatedAt());
orderEntity.setPaymentMode(orderDto.getPaymentMode());
orderEntity.setTotalAmount(orderDto.getTotalAmount());
// set the seller
UserEntity userEntity = modelMapper.map(orderDto.getSeller(), UserEntity.class);
orderEntity.setSeller(userEntity);
List<OrderProductEntity> orderProductEntities = new ArrayList<>();
// set the products
for (int i = 0; i < orderDto.getOrderProducts().size(); i++) {
ProductDto productDto = orderDto.getOrderProducts().get(i);
OrderProductEntity orderProductEntity = modelMapper.map(orderDto.getOrderProducts().get(i), OrderProductEntity.class);
orderProductEntities.add(orderProductEntity);
orderDto.getOrderProducts().set(i, productDto);
}
orderEntity.setOrderProducts(orderProductEntities);
OrderEntity storedOrder = orderRepository.save(orderEntity);
OrderDto returnValue = modelMapper.map(storedOrder, OrderDto.class);
return returnValue;
}
I have 3 issues :
I save the order in the database but the seller is not persisted
In the order product table datas are not persisted.
And i obtain an error message in my rest response :
"trace": "org.modelmapper.MappingException: ModelMapper mapping errors: Converter org.modelmapper.internal.converter.CollectionConverter#685b36d6 failed to convert java.util.List to java.util.List.error...

ModelMapper issue with mapping basic POJOS

I have 2 basic POJOs that i use to build a json object :
public class ProductCreateRequestModel {
private String name;
private double price;
private int qty;
private String imgPath;
private CategoryRequestCreateProductModel category;
}
public class CategoryRequestCreateProductModel {
private String name;
private String categoryKeyId;
}
Basically it allow me to use a simple json like this one :
{
"name": "Pizza,
"price": 344.0,
"qty": 15,
"imgPath": "new/pathImage",
"category": {
"categoryKeyId": "23ume70Fu6yqyGUWfQkW110P4ko3gZ",
"name": "Starter"
}
}
I want to send this JSON and persist datas and i expect an object in return that i build with this POJO:
public class ProductRest {
private String productKeyId;
private String name;
private double price;
private int qty;
private String imgPath;
private CategoryRest category;
}
In my controller i just have to call a method which use PostMapping
#PostMapping(
consumes = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE },
produces = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE }
)
public ProductRest createProduct(#RequestBody ProductCreateRequestModel productCreateRequestModel) throws Exception {
ProductRest returnValue = new ProductRest();
if(productCreateRequestModel.getName().isEmpty() || productCreateRequestModel.getPrice() <= 0)
throw new ApplicationServiceException(ErrorMessages.MISSING_REQUIRED_FIELDS.getErrorMessage());
ModelMapper modelMapper = new ModelMapper();
ProductDto productDto = modelMapper.map(productCreateRequestModel, ProductDto.class);
ProductDto createdProduct = productService.createProduct(productDto);
returnValue = modelMapper.map(createdProduct, ProductRest.class);
return returnValue;
}
My service layer is actually doing nothing special :
#Override
public ProductDto createProduct(ProductDto productDto) {
return productDto;
}
My DTO layer contains the following fields :
#Getter #Setter
public class ProductDto implements Serializable {
// ommit this member and do not generate getter / setter
#Getter(AccessLevel.NONE)
#Setter(AccessLevel.NONE)
private static final long serialVersionUID = 1L;
private Long id;
private String productKeyId;
private String name;
private double price;
private int availableQty;
private String imgPath;
private CategoryDto category = new CategoryDto();
}
#Getter #Setter
public class CategoryDto implements Serializable {
#Getter(AccessLevel.NONE)
#Setter(AccessLevel.NONE)
private static final long serialVersionUID = 1L;
private long id;
private String categoryKeyId;
private String name;
private CategoryDto parentCategory;
private List<CategoryDto> subCategories;
private String parentCategoryKeyId;
private Long parentCategoryId;
}
While trying to run this basic code I obtain an error message :
java.lang.NumberFormatException: For input string: "23ume70Fu6yqyGUWfQkW110P4ko3gZ"

Spring JPA Update Entity

I'm trying to update my user entity and I have an error that comes to mind:
ERROR: A NULL value violates the NOT NULL constraint of the "id" column Detail: The failed row contains (null, 1, 1)
The problem surely stems from my relationship between user and profile which is n-n
public class Utilisateur implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private Integer id;
private Integer fixe;
private Boolean deleted;
private Boolean actif;
private String email;
private Integer mobile;
private String motDePasse;
private String nom;
private String prenom;
#ManyToMany
private List<Profil> profils = new ArrayList<Profil>();
public Utilisateur() {
}
}
public class Profil implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private Integer id;
private String codeProfil;
private String libelleProfil;
#JsonManagedReference
#ManyToMany
private List<MenuAction> menuActions = new ArrayList<MenuAction>();
public Profil() {
}
}
How you generate value for your id?
Seems you need some way to generate value for you ID.
For example, use #GeneratedValue, like:
#GeneratedValue(strategy = IDENTITY)

How to lazy fetch with spring data repository?

Database Tables
post
tag
ref_post_tag
post and tag has a Many-to-Many relationship
Entities
Post
#Entity
#Table(name = "post")
public class Post implements Serializable{
private static final long serialVersionUID = 1783734013146305964L;
public enum Status {
DRAFT, REMOVED, LIVE;
}
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO)
private String id;
#Column(name = "title")
private String title;
#Column(name = "create_time")
private LocalDateTime createTime;
#Column(name = "update_time")
private LocalDateTime updateTime;
#Column(name = "content")
private String content;
#Column(name = "status")
#Enumerated(EnumType.STRING)
private Status status;
#ManyToMany
#JoinTable(
name = "ref_post_tag",
joinColumns = #JoinColumn(name="post_id",referencedColumnName = "id"), inverseJoinColumns = #JoinColumn(name="tag_id", referencedColumnName = "id"))
private List<Tag> tagList;
...
}
Tag
#Entity
#Table(name="tag")
public class Tag implements Serializable{
private static final long serialVersionUID = -7015657012681544984L;
#Id
#Column(name="id")
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Column(name="name")
private String name;
#Column(name="description")
private String description;
#ManyToMany(mappedBy = "tagList")
private List<Post> postList;
public Integer getId() {
return id;
}
...
}
Tag Repo
public interface TagRepo extends CrudRepository<Tag, Integer>{
}
service implementation
#Service
public class TagServiceImpl implements TagService{
#Autowired
private TagRepo tagRepo;
#Override
public void addTag(Tag tag) {
tagRepo.save(tag);
}
#Override
public Tag getTag(Integer id) {
Tag tag = tagRepo.findOne(id);
return tag;
}
#Override
public List<Tag> findAllTags() {
return CollectionUtil.toArrayList(tagRepo.findAll());
}
}
sample test (Updated)
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = TestContextConfiguration.class)
#Transactional
public abstract class ServiceTest {
}
public class TagServiceTest extends ServiceTest{
#Autowired
private TagService tagService;
#Autowired
private TagRepo tagRepo;
#Test
#Transactional
public void addTag() throws Exception {
Tag tag = new Tag();
tag.setName("new tag");
tag.setDescription("this is a new tag");
tagService.addTag(tag);
Tag tagCreated = tagRepo.findOne(tag.getId());
assertNotNull(tagCreated);
assertEquals(tagCreated.getName(), tag.getName());
}
#Test
public void getTag() throws Exception {
Tag tag = tagService.getTag(1); // tag "java" has an ID of "1"
assertNotNull(tag);
assertEquals(tag.getName(), "java");
assertEquals(143,tag.getPostList().size()); // 143 posts under tag "java"
}
}
Question
The sample test case passes. It means that the postList in fetched Tag is also eagerly fetched and filled.
Is Spring data repository's methods eagerly fetching by default?
If yes, what is the best way to change this to lazy fetching?

Resources