I am trying to setup a Spring Data Elastic Project. Here is my document...
{
"_index": "_idx1",
"_type": "_doc",
"_id": "440986688",
"_version": 9,
"_seq_no": 22175768,
"_primary_term": 25,
"found": true,
"_source": {
"dto": {
"evidencePath": "path",
"disclosurePath": "dPath",
"allowedCommands": [],
"actionText": "View - No action required",
"closedNokReason": null,
"closedNokComment": null,
"evidenceDocuments": [
{
"identifier": "7355580062",
"purpose": "COMMENT",
"description": "Task submitted",
"date": "2022/01/20 15:57:54",
"dateISO": null,
"provider": "Andrew",
"contentStreamMimeType": "v_comment",
"contentStreamLength": 14,
"fileName": "comment_29160_1893869507.txt",
"downloader": null,
"downloaded": null,
"wfdId": null,
"draft": false,
"controlOwner": null,
"controlEmail": null,
"controlProvisionId": null,
"type": "COMMENT"
}
],
"referenceDocuments": [
],
"message": null,
"type": "Dash",
"owner": "Andrew "
},
"id": 440986688,
"guiKey": "ap_apr_review_",
"followupAllowed": false,
"lastFollowup": null,
"consolidatedMetric": "Review",
"riskCategory": "Unassigned",
"disclosureData": true,
"disclosureDataActionText": "This is submitted. ",
"disclosureDataRows": [
{
"identifier": "4290018.00001",
"evProvProcessId": "440986688",
"usPersonEmployee": "Yes"
}
],
"disclosureDataEnrichments": true,
"ftdDelegateEmails": null,
"ftdOwnerEmails": null,
"reviewRequired": true,
"gateDate": 1645814815901,
"wspNumber": null,
"wspBook": null,
"wspSubBook": null,
"other": {},
"actionType": "FYI",
"actionTypes": [],
"allowedActions": [],
"action": false,
"actionText": "View - No action required",
"wfdId": 111964,
"message": ""
}
}
Here is my ma document mapping...
#Document(indexName = "_idx1")
public class TaskBean {
#Field(type = FieldType.Nested)
private DtoBean dto;
#Id
private String id;
#Field(type = FieldType.Text)
private String wsp;
#Field(type = FieldType.Text)
private String wspId;
#Field(type = FieldType.Text)
private String control;
#Field(type = FieldType.Text)
private String evProvComment;
#Field(type = FieldType.Text)
private String reason;
#Field(type = FieldType.Text)
private String delegate;
#Field(type = FieldType.Text)
private String delegateEmail;
#Field(type = FieldType.Text)
private String delegationType;
#Field(type = FieldType.Text)
private String delegateId;
#Field(type = FieldType.Text)
private String owner;
#Field(type = FieldType.Text)
private String ownerEmail;
#Field(type = FieldType.Text)
private String ownerUBR;
#Field(type = FieldType.Text)
private List<String> wspApplicability;
#Field(type = FieldType.Text)
private String commit;
#Field(type = FieldType.Text)
private String templateFiles;
#Field(type = FieldType.Text)
private String alertText;
#Field(type = FieldType.Text)
private String guiKey;
#Field(type = FieldType.Text)
private String followupAllowed;
#Field(type = FieldType.Text)
private String lastFollowup;
#Field(type = FieldType.Text)
private String consolidatedMetric;
#Field(type = FieldType.Text)
private String riskCategory;
#Field(type = FieldType.Text)
private String disclosureData;
#Field(type = FieldType.Text)
private String disclosureDataActionText;
#Field(type = FieldType.Nested)
private List<DisclosureRow> disclosureDataRows;
#Field(type = FieldType.Text)
private String disclosureDataEnrichments;
#Field(type = FieldType.Text)
private String ftdDelegateEmails;
#Field(type = FieldType.Text)
private String ftdOwnerEmails;
#Field(type = FieldType.Text)
private String reviewRequired;
#Field(type = FieldType.Text)
private String gateDate;
#Field(type = FieldType.Text)
private String wspNumber;
#Field(type = FieldType.Text)
private String wspBook;
#Field(type = FieldType.Text)
private String wspSubBook;
#Field(type = FieldType.Text)
private String other;
#Field(type = FieldType.Text)
private String actionType;
#Field(type = FieldType.Text)
private List<String> actionTypes;
#Field(type = FieldType.Text)
private List<String> allowedActions;
#Field(type = FieldType.Text)
private String action;
#Field(type = FieldType.Text)
private String actionText;
#Field(type = FieldType.Text)
private String wfdId;
#Field(type = FieldType.Text)
private String message;
}
My configuration class....
#Configuration
#EnableElasticsearchRepositories(basePackages = "com.mi.repository")
public class ReactiveRestClientConfig {
#Value("${elasticsearch.host}")
private String EsHost;
#Value("${elasticsearch.port}")
private int EsPort;
#Value("${elasticsearch.user}")
private String user;
#Value("${elasticsearch.password}")
private String password;
#Bean
public RestHighLevelClient client() {
//System.out.println(EsHost);
InetSocketAddress proxyAddress = null;
try {
proxyAddress = new InetSocketAddress( InetAddress.getByName(EsHost), EsPort) ;
}catch(Exception e) {
}
ClientConfiguration clientConfiguration
= ClientConfiguration.builder()
.connectedTo(proxyAddress)
.withConnectTimeout(Duration.ofSeconds(50))
.withSocketTimeout(Duration.ofSeconds(50))
.withBasicAuth(EsUser, EsPassword)
.build();
return RestClients.create(clientConfiguration).rest();
}
#Bean
public ElasticsearchOperations elasticsearchTemplate() {
return new ElasticsearchRestTemplate(client());
}
}
And finally, Service class...
#Component
public class TaskService {
#Autowired
private TaskBeanRepository taskBeanRepository;
public TaskBean findById(String id) {
Optional<TaskBean> taskBean = taskBeanRepository.findById(id);
if(taskBean.isPresent()) {
return taskBean.get();
}
return null;
}
}
I have created a controller and calling this method through REST. Even after passing correct Id 440986688 to this method it is returning 404 not found. Any issue with my mapping?
Related
The code was working normally and I've tried in every way to solve it and I couldn't, it may be that after I transformed the MultipartFile into an array this happened
#RestController
#RequestMapping("products")
public class ProductController {
#Autowired
private ProductService productService;
#PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
#Transactional
public ResponseEntity<ShowProductsDTO> registerProduct(
#RequestBody #Valid ProductDTO dto,
#RequestParam(name = "files", required = true) MultipartFile[] files,
UriComponentsBuilder uriBuilder) {
ShowProductsDTO showProductsDTO = null;
try {
showProductsDTO = productService.save(dto, files);
} catch (IOException e) {
e.printStackTrace();
}
var uri = uriBuilder.path("/products/{id}").buildAndExpand(showProductsDTO.id()).toUri();
return ResponseEntity.created(uri).body(showProductsDTO);
}
DTO
public record ProductDTO(
#NotBlank
String name,
#NotBlank
String description,
#NotNull
#NumberFormat
BigDecimal price,
#NumberFormat
#NotNull
Integer quantity,
#NotNull
Boolean active,
#NotNull
Long sub_category_id
) {
}
Error console
Resolved [org.springframework.web.HttpMediaTypeNotSupportedException:
Content-Type
'multipart/form-data;boundary=--------------------------816548045966415708649211;charset=UTF-8'
is not supported]
Postman body > raw > json
{
"name": "Nome do produto",
"description": "descricao do produto",
"price": "2500.00",
"quantity": "2",
"active": "true",
"sub_category_id": "1"
}
Postman > body > form-data
KEY "files", TYPE file, VALUE uma imagem minha em png
Error postman
{
"timestamp": "2023-01-11T06:15:43.455+00:00",
"status": 415,
"error": "Unsupported Media Type",
"message": "Content-Type 'multipart/form-data;boundary=--------------------------056640214920648036756520;charset=UTF-8' is not supported.",
"path": "/products"
}
Product entity
#Table(name = "products")
#Entity(name = "Product")
#Getter
#Setter
#NoArgsConstructor
#EqualsAndHashCode(of = "id")
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(length = 100, unique = true, nullable = false)
private String name;
#Column(nullable = false, columnDefinition = "TEXT")
private String description;
#Column(length = 8, nullable = false, columnDefinition = "NUMERIC(8,2)")
private BigDecimal price;
#Column(nullable = false, columnDefinition = "INT")
private Integer quantity;
#Column(nullable = false, columnDefinition = "BOOLEAN")
private Boolean active;
#CollectionTable(name = "products_files",
joinColumns =
#JoinColumn(name = "product_id", referencedColumnName = "id"))
private List<String> productFiles;
#JoinColumn(name = "sub_category_id")
#ManyToOne(fetch = FetchType.EAGER)
private SubCategory subCategory;
how do I fix this error?
Change your attribute to #PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
and call your api using Postman body > raw > json.
The thing is, Content-Type: form-data handles file requests.
I am studying spring boot data using this API SWAPI, I did almost things but now I dont know how to map the relationship about two lists, above you can see my code and entities.
Entity Film
#Data
#Entity
public class Film extends Persistent<Long> {
private String title;
#JsonProperty(value = "episode_id")
private int episodeId;
#JsonProperty(value = "opening_crawl")
#Column(columnDefinition = "CLOB")
private String openingCrawl;
private String director;
private String producer;
#JsonDeserialize(converter = StringToLocalDateConverter.class)
#JsonProperty(value = "release_date")
private LocalDate releaseDate;
#JsonDeserialize(converter = ApiURLToEntitiesConverter.class)
#ManyToMany(mappedBy = "films")
private List<Person> characters;
#JsonDeserialize(converter = StringToLocalDateTimeConverter.class)
private LocalDateTime created;
#JsonDeserialize(converter = StringToLocalDateTimeConverter.class)
private LocalDateTime edited;
private String url;
}
Entity Person
#Data
#Entity
public class Person extends Persistent<Long> {
private String name;
private String height;
private String mass;
#JsonProperty(value = "hair_color")
private String hairColor;
#JsonProperty(value = "skin_color")
private String skinColor;
#JsonProperty(value = "eye_color")
private String eyeColor;
#JsonProperty(value = "birth_year")
private String birthYear;
private String gender;
#JsonDeserialize(converter = ApiURLToEntityConverter.class)
#JoinColumn(name = "planet_id", foreignKey = #javax.persistence.ForeignKey(name = "none"))
#OneToOne(optional = true)
private Planet homeworld;
#JsonDeserialize(converter = ApiURLToEntitiesConverter.class)
#ManyToMany
#JoinTable(
name = "film_person",
joinColumns = #JoinColumn(name = "film_fk", referencedColumnName = "id", nullable = true),
inverseJoinColumns = #JoinColumn(name = "person_fk", referencedColumnName = "id", nullable = true))
private List<Film> films;
#JsonDeserialize(converter = StringToLocalDateTimeConverter.class)
private LocalDateTime created;
#JsonDeserialize(converter = StringToLocalDateTimeConverter.class)
private LocalDateTime edited;
private String url;
}
I am trying to use the spring jpa method to saveAll
#Override
public List<T> insertAll(List<T> entities) {
for (Persistent entity : entities) {
Set<ConstraintViolation<Persistent>> violations = validator.validate(entity);
if (violations != null && !violations.isEmpty()) {
throw new ConstraintViolationException(violations);
}
}
return repository.saveAll(entities);
}
Converter Method
#Override
public List convert(List<String> s) {
if (s == null || s.isEmpty()) {
return null;
}
List objetos = new LinkedList();
for (String url : s) {
if (url.contains("people")) {
objetos.add(Util.getPerson(url));
}
if (url.contains("planets")) {
objetos.add(Util.getPlanet(url));
}
if (url.contains("starships")) {
objetos.add(Util.getStarship(url));
}
if (url.contains("vehicles")) {
objetos.add(Util.getVehicle(url));
}
if (url.contains("species")) {
objetos.add(Util.getSpecie(url));
}
}
return objetos;
}
}
Util method
public static Person getPerson(String characterApiUrl) {
if (characterApiUrl == null || characterApiUrl.isEmpty()) {
return null;
}
Person person = new Person();
person.setId(StringUtil.getIdEntity(characterApiUrl, "people/"));
return person;
}
The relationship table is being created but no populated
Using spring boot version: 2.2.6.RELEASE | Database: SqlServer 2008 | org.hibernate.dialect.SQLServer2008Dialect.
When using a converter for mapping the enumeration of a column of the type "TINYINT" that would be referring to "Byte" in java is presenting the following error:
No Dialect mapping for JDBC type: 277630005, when hibernate ddl for initial db.
However, when doing the direct mapping as Byte without using enumeration, it works correctly.
Converter:
#Converter
public class CharacterClassConverter implements AttributeConverter<CharacterClassIndicator, Byte> {
#Override
public Byte convertToDatabaseColumn(CharacterClassIndicator characterClassIndicator) {
return characterClassIndicator != null ? characterClassIndicator.getCode() : null;
}
#Override
public CharacterClassIndicator convertToEntityAttribute(Byte code) {
return Stream.of(CharacterClassIndicator.values())
.filter(value -> value.getCode().equals(code))
.findFirst()
.orElseThrow(UnsupportedOperationException::new);
}
}
Enum:
public enum CharacterClassIndicator {
DARK_WIZARD(0, "DK", "Dark Wizard"),
SOUL_MASTER(1, "SM", "Soul Master"),
GRAND_MASTER(2, "GM", "Grand Master"),
DARK_KNIGHT(16, "DK", "Dark Knight"),
BLADE_KNIGHT(17, "BK", "Blade Knight"),
BLADE_MASTER(18, "BM", "Blade Master"),
FAIRY_ELF(32, "FE", "Fairy Elf"),
MOUSE_ELF(33, "ME", "Mouse Elf"),
HIGH_ELF(34, "HE", "High Elf"),
DARK_LORD(48, "DL", "Dark Lord"),
LORD_EMPEROR(49, "LE", "Lord Emperor"),
MAGIC_GLADIATOR(64, "MG", "Magic Gladiator"),
DUEL_MASTER(65, "DM", "Duel Master");
private final Byte code;
private final String initials;
private final String name;
CharacterClassIndicator(Integer code, String initials, String name) {
this.code = code.byteValue();
this.initials = initials;
this.name = name;
}
public Byte getCode() {
return code;
}
public String getInitials() {
return initials;
}
public String getName() {
return name;
}
}
The entity code:
#Entity
#Table(name = "Character")
public class Character {
#Id
#Column(name = "AccountID")
private String id;
#Column(name = "Name")
private String name;
#Column(name = "Class")
#Convert(converter = CharacterClassConverter.class) // if remove this line and change type to Byte, works correctly
private CharacterClassIndicator characterClass;
#Column(name = "cLevel")
private Integer level;
#Column(name = "Strength")
private Short strenght;
#Column(name = "Dexterity")
private Short dexterity;
#Column(name = "Vitality")
private Short vitality;
#Column(name = "Energy")
private Short energy;
#Column(name = "Resets")
private Integer resets;
.... gets and setters
}
Would anyone have an idea how to solve?
Use columnDefinition
#Column(name = "Class", columnDefinition = "TINYINT")
I'm trying to get into GraphQL and I followed a tutorial for a simple GraphQL + Spring + MySQL application, and I remade it for my own database. But when I try to execute my findAllDocuments query, I get this response in Postman:
"data": null,
"errors": [
{
"message": "Validation error of type FieldUndefined: Field 'findAllDocuments' in type 'query' is undefined # 'findAllDocuments'",
"locations": [
{
"line": 2,
"column": 5,
"sourceName": null
}
],
"description": "Field 'findAllDocuments' in type 'query' is undefined",
"validationErrorType": "FieldUndefined",
"queryPath": [
"findAllDocuments"
],
"errorType": "ValidationError",
"path": null,
"extensions": null
}
]
}
This is the entity I'm trying to get (it has some complex datatypes like Group or Media, that have similar implementation as Document class, I didn't include them to save space):
#Table(name = "documents")
public class Document {
#Id
#Column(name = "doc_id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column(name = "title")
private String title;
#Column(name = "data")
private String data;
#Column(name = "data_asc")
private String dataAsc;
#Column(name = "external_link")
private String externalLink;
#OneToMany
#JoinColumn(name = "doc_id")
private List<DocumentForum> forums;
#Column(name = "navbar")
private String navbar;
#Column(name = "date_created")
private Date dateCreated;
#Column(name = "publish_start")
private Date publishStart;
#Column(name = "publish_end")
private Date publishEnd;
#OneToOne
#JoinColumn(name = "user_id")
private UserDetails author;
#OneToOne
#JoinColumn(name = "group_id")
private Group group;
#OneToMany(mappedBy = "document")
private List<Media> media;
#Column(name = "temp_id")
private Integer tempId;
#Column(name = "views_total")
private int viewsTotal;
#Column(name = "views_month")
private int viewsMonth;
#Column(name = "searchable")
private boolean searchable;
#Column(name = "available")
private boolean available;
#Column(name = "cacheable")
private boolean cacheable;
#Column(name = "file_name")
private String fileName;
#Column(name = "file_change")
private Date fileChange;
#Column(name = "sort_priority")
private int sortPriority;
#Column(name = "header_doc_id")
private int headerDocId;
#Column(name = "menu_doc_id")
private int menuDocId;
#Column(name = "footer_doc_id")
private int footerDocId;
#Column(name = "password_protected")
private String passwordProtected;
#Column(name = "html_head")
private String htmlHead;
#Column(name = "perex_place")
private String perexPlace;
#Column(name = "perex_image")
private String perexImage;
#Column(name = "perex_group")
private String perexGroup;
#Column(name = "show_in_menu")
private boolean showInMenu;
#Column(name = "event_date")
private Date eventDate;
#Column(name = "virtual_path")
private String virtualPath;
#Column(name = "sync_id")
private int syncId;
#Column(name = "sync_status")
private int syncStatus;
#Column(name = "logon_page_doc_id")
private int logonPageDocId;
#Column(name = "right_menu_doc_id")
private int rightMenuDocId;
#Column(name = "field_a")
private String fieldA;
#Column(name = "field_b")
private String fieldB;
#Column(name = "field_c")
private String fieldC;
#Column(name = "field_d")
private String fieldD;
#Column(name = "field_e")
private String fieldE;
#Column(name = "field_f")
private String fieldF;
#Column(name = "field_g")
private String fieldG;
#Column(name = "field_h")
private String fieldH;
#Column(name = "field_i")
private String fieldI;
#Column(name = "field_j")
private String fieldJ;
#Column(name = "field_k")
private String fieldK;
#Column(name = "field_l")
private String fieldL;
#Column(name = "disable_after_end")
private boolean disableAfterEnd;
#Column(name = "forum_count")
private int forumCount;
#Column(name = "field_m")
private String fieldM;
#Column(name = "field_n")
private String fieldN;
#Column(name = "field_o")
private String fieldO;
#Column(name = "field_p")
private String fieldP;
#Column(name = "field_q")
private String fieldQ;
#Column(name = "field_r")
private String fieldR;
#Column(name = "field_s")
private String fieldS;
#Column(name = "field_t")
private String fieldT;
#Column(name = "require_ssl")
private boolean requireSsl;
#Column(name = "root_group_l1")
private Integer rootGroupL1;
#Column(name = "root_group_l2")
private Integer rootGroupL2;
#Column(name = "root_group_l3")
private Integer rootGroupL3;
*********SETTER AND GETTERS*********
This is the .graphqls file for Document class:
scalar Date
type Document{
id: Int!
title: String!
data: String!
dataAsc: String!
externalLink: String!
forums: [DocumentForum]!
navbar: String!
dateCreated: Date!
publishStart: Date
publishEnd: Date
author: UserDetails!
group: Group!
media: [Media]!
tempId: Int!
viewsTotal: Int!
viewsMonth: Int!
searchable: Boolean!
available: Boolean!
cacheable: Boolean!
fileName: String
fileChange: Date
sortPriority: Int!
headerDocId: Int!
menuDocId: Int!
footerDocId: Int!
passwordProtected: String
htmlHead: String!
perexPlace: String!
perexImage: String!
perexGroup: String
showInMenu: Boolean!
eventDate: Date
virtualPath: String!
syncId: Int!
syncStatus: Int!
logonPageDocId: Int!
rightMenuDocId: Int!
fieldA: String!
fieldB: String!
fieldC: String!
fieldD: String!
fieldE: String!
fieldF: String!
fieldG: String!
fieldH: String!
fieldI: String!
fieldJ: String!
fieldK: String!
fieldL: String!
disableAfterEnd: Boolean!
forumCount: Int!
fieldM: String!
fieldN: String!
fieldO: String!
fieldP: String!
fieldQ: String!
fieldR: String!
fieldS: String!
fieldT: String!
requireSsl: Boolean!
rootGroupL1: Int
rootGroupL2: Int
rootGroupL3: Int
}
type Query {
findAllDocuments: [Document]!
}
This is the Query resolver class:
public class Query implements GraphQLQueryResolver {
private final DocumentRepository documentRepository;
private final DocumentForumRepository documentForumRepository;
private final GroupRepository groupRepository;
private final MediaRepository mediaRepository;
private final UserDetailsRepository userDetailsRepository;
#Autowired
public Query(DocumentRepository documentRepository,
DocumentForumRepository documentForumRepository,
GroupRepository groupRepository,
MediaRepository mediaRepository,
UserDetailsRepository userDetailsRepository){
this.documentRepository = documentRepository;
this.documentForumRepository = documentForumRepository;
this.groupRepository = groupRepository;
this.mediaRepository = mediaRepository;
this.userDetailsRepository = userDetailsRepository;
}
public Iterable<Document> findAllDocuments(){
return documentRepository.findAll();
}
public Iterable<DocumentForum> findAllDocumentForums(){
return documentForumRepository.findAll();
}
public Iterable<Group> findAllGroups(){
return groupRepository.findAll();
}
public Iterable<Media> findAllMedia(){
return mediaRepository.findAll();
}
}
And this is the DocumentResolver class:
public class DocumentResolver implements GraphQLResolver<Document> {
private DocumentForumRepository documentForumRepository;
private GroupRepository groupRepository;
private MediaRepository mediaRepository;
private UserDetailsRepository userDetailsRepository;
#Autowired
public DocumentResolver(DocumentForumRepository documentForumRepository,
GroupRepository groupRepository,
MediaRepository mediaRepository,
UserDetailsRepository userDetailsRepository){
this.documentForumRepository = documentForumRepository;
this.groupRepository = groupRepository;
this.mediaRepository = mediaRepository;
this.userDetailsRepository = userDetailsRepository;
}
public List<DocumentForum> getForums(Document document){
return documentForumRepository.findAllById(document.getId());
}
public UserDetails getAuthor(Document document) throws ObjectNotFoundException {
Optional<UserDetails> optionalUserDetails = userDetailsRepository.findById(document.getId());
if(optionalUserDetails.isPresent()){
return optionalUserDetails.get();
}else{
throw new ObjectNotFoundException();
}
}
public Group getGroup(Document document) throws ObjectNotFoundException {
Optional<Group> optionalGroup = groupRepository.findById(document.getId());
if(optionalGroup.isPresent()){
return optionalGroup.get();
}else{
throw new ObjectNotFoundException();
}
}
public List<Media> getMedia(Document document) {
return mediaRepository.findAllById(document.getId());
}
}
The query I try to send from Postman:
{
findAllDocuments{
id
title
data
}
}
Everything works in my smaller project and I can't pinpoint what's the problem here. If anything else is needed, please let me know and I'll provide it. Thank you.
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...