Home > Net >  Spring Boot Rest API Issues
Spring Boot Rest API Issues

Time:11-03

I'm trying to implement a Spring Boot Rest API using Spring Data Jdbc with H2 Database. This is a microservice, and I'm trying to send a POST request to the microservice from an angular app. I know my POST is working correctly from Angular. Inside of microservice, I am trying to save the POST request to a local H2 database. This should be relatively straight forward based on documentation I've read online, but I am getting error messages. Any help would be greatly appreciated. Here are the files I have setup inside my spring boot microservice (titled 'order'):

OrderController.java:

package com.clothingfly.order;

import java.util.ListIterator;
import org.springframework.web.client.RestTemplate;
import com.clothingfly.order.Model.Item;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.clothingfly.order.Model.Order;

@RestController
@CrossOrigin(origins = "http://localhost:4200")
public class OrderController {


    @Autowired
    TempOrderRepository orderRepository;

    @PostMapping("/order")
    public Order postOrder(@RequestBody Order order) {
      Order _order = orderRepository.save(new Order(order.getId(), order.getAddress(), order.getPayment(), order.getItems()));
      return _order;
    }
}

TempOrderRepository.java:

package com.clothingfly.order;

import org.springframework.data.jpa.repository.JpaRepository;
import com.clothingfly.order.Model.Order;



public interface TempOrderRepository extends JpaRepository<Order, Long>{

}

OrderApplication.java:

package com.clothingfly.order;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class OrderApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }

}

And I have a model named Order.java:

package com.clothingfly.order.Model;


import java.util.List;

import javax.persistence.*;

import org.springframework.data.annotation.Id;

@Entity
@Table(name = "orders")
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @Column(name = "Address")
    private Address address;

    @Column(name = "Payment")
    private PaymentInfo payment;

    @Column(name = "Items")
    private List<Item> items;

    @Column(name = "Error")
    private String error;

    public Order() {

    }

    public Order(long id, Address address, PaymentInfo payment, List<Item> items){
        this.id = id;
        this.address = address;
        this.payment = payment;
        this.items = items;
        this.error = "";
    }

    public long getId() {
        return id;
    }

    public Address getAddress() {
        return address;
    }


    public PaymentInfo getPayment() {
        return payment;
    }


    public List<Item> getItems() {
        return items;
    }

    public String getError() {
        return error;
    }

    public void setError(String error) {
        this.error = error;
    }

}

The Order model takes in three other models: Item.java:

package com.clothingfly.order.Model;

import javax.persistence.*;

@Entity
@Table(name = "items")
public class Item {

    @Id
    @GeneratedValue
    @Column(name = "id")
    private long id;

    @Column(name = "name")
    private String name;

    @Column(name = "price")
    private float price;

    @Column(name = "imageUrl")
    private String imageUrl;

    @Column(name = "quantity")
    private long quantity;

    @Column(name = "inventory")
    private long inventory;

    public long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public float getPrice() {
        return price;
    }

    public long getQuantity() {
        return quantity;
    }

    public long getInventory() {
        return inventory;
    }

    public String getImageUrl(){
        return imageUrl;
    }

    public void setInventory(long inventory) {
        this.inventory = inventory;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setPrice(float price) {
        this.price = price;
    }

    public void setQuantity(long quantity) {
        this.quantity = quantity;
    }

    public Item(long id, String name, float price, long quantity, long inventory, String imageUrl) {
        this.id = id;
        this.name = name;
        this.price = price;
        this.quantity = quantity;
        this.inventory = inventory;
        this.imageUrl = imageUrl;
    }

    public Item() {

  }
}

Address.java:

package com.clothingfly.order.Model;
import javax.persistence.*;
@Entity
@Table(name = "addresses")
public class Address {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

  @Column(name = "firstName")
  private String firstName;

  @Column(name = "lastName")
  private String lastName;

  @Column(name = "address")
  private String address;

  @Column(name = "country")
  private String country;

  @Column(name = "apartmentNo")
  private String apartmentNo;

  @Column(name = "state")
  private String state;

  @Column(name = "city")
  private String city;

  @Column(name = "zipcode")
  private String zipcode;


  public Address() {

  }

  public Address(String firstName, String lastName, String address, String country, String apartmentNo, String state,
            String city, String zipcode) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.address = address;
    this.country = country;
    this.apartmentNo = apartmentNo;
    this.state = state;
    this.city = city;
    this.zipcode = zipcode;
    }

  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 getCountry() {
    return country;
  }

  public void setCountry(String country) {
    this.country = country;
  }

  public String getApartmentNo() {
    return apartmentNo;
  }

  public void setApartmentNo(String apartmentNo) {
    this.apartmentNo = apartmentNo;
  }

  public String getState() {
    return state;
  }

  public void setState(String state) {
    this.state = state;
  }

  public String getCity() {
    return city;
  }

  public void setCity(String city) {
    this.city = city;
  }

  public String getZipcode() {
    return zipcode;
  }

  public void setZipcode(String zipcode) {
    this.zipcode = zipcode;
  }
}

PaymentInfo.java:

package com.clothingfly.order.Model;

import javax.persistence.*;
@Entity
@Table(name = "payments")
public class PaymentInfo {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

  @Column(name = "cardHolder")
  private String cardHolder;

  @Column(name = "cardNumber")
  private String cardNumber;

  @Column(name = "expirationDate")
  private String expirationDate;

  @Column(name = "cvv")
  private String cvv;



  public PaymentInfo(String cardHolder, String cardNumber, String expirationDate, String cvv) {
    this.cardHolder = cardHolder;
    this.cardNumber = cardNumber;
    this.expirationDate = expirationDate;
    this.cvv = cvv;
  }

  public String getCardHolder() {
    return cardHolder;
  }

  public void setCardHolder(String cardHolder) {
    this.cardHolder = cardHolder;
  }

  public String getCardNumber() {
    return cardNumber;
  }

  public void setCardNumber(String cardNumber) {
    this.cardNumber = cardNumber;
  }

  public String getExpirationDate() {
    return expirationDate;
  }

  public void setExpirationDate(String expirationDate) {
    this.expirationDate = expirationDate;
  }

  public String getCvv() {
    return cvv;
  }

  public void setCvv(String cvv) {
    this.cvv = cvv;
  }
}

I'm getting the following error when trying to run microservice: Unable to build Hibernate SessionFactory; nested exception is org.hibernate.MappingException: Could not determine type for: com.clothingfly.order.Model.Address, at table: orders, for columns: [org.hibernate.mapping.Column(address)]

How would I go about fixing this? I want to be able to display all of my models inside a table.

I tried changing Address model so that it only returns a string of the city, but that seemed to cause more issues than anything.

CodePudding user response:

you have to tell hibernate that the Address object is coming from another table and how to join those tables, since your orders table most likely does not have a column which contains the hole address but the the address id/ primary key of the address as foreign key. this is possible, depending if you have 1:1, 1:n, n:1 or n:m relations with the corresponding @OneToOne, @OneToMany, @ManyToOne and @ManyToMany annotations. for your example it could be something like

@OneToOne
@JoinColumn(name = "address_id", referencedColumnName = "id")
private Address address;

CodePudding user response:

Note, one to one will always cause you an issue, always better to implement many to one and one to many. and add it to both entities you are mapping. It will do the same job with no errors.

First, create packages, and don't place everything in one package. create

package com.clothingfly.repo or  com.clothingfly.order.repo
package com.clothingfly.controller or  com.clothingfly.order.controller

Secondly, add the annotation @Repository to your repository interface

package com.clothingfly.repo;
import org.springframework.data.jpa.repository.JpaRepository;
import com.clothingfly.order.Model.Order;


@Repository
public interface TempOrderRepository extends JpaRepository<Order, Long>{

}

Thirdly, add the annotation @EnableJpaRepositories(basePackages = "com.clothingfly.repo") to your main application class.

package com.clothingfly.order;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EnableJpaRepositories(basePackages = "com.clothingfly.repo")
public class OrderApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }

}

Lastly, this will not work correctly. Not sure what you are doing here.

@Column(name = "Address")
private Address address;

Try this: add this in your address entity

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name="order_id", nullable = false)// add this column 
    // order_id in your Address database not the entity
    @OnDelete(action = OnDeleteAction.CASCADE)
    @JsonIgnore
    private Order order;

Then, add this to your Order class.

       @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="order")
        @OnDelete(action = OnDeleteAction.CASCADE)
        @JsonIgnore
        List<Address> address = new ArrayList<Address>(); // I use list cause sometimes it throws an error
// try to simply use this, if it throws expection then use the list
      //private Address address;

Your Order constructor should be like:

public Order(long id, List<Address> address ...etc

Or simply

public Order(long id, Address address ...etc

Do this for all your mapped entities and don't forget to add setters and getters for all fields.

  • Related