1

I have two classes, Customer and ShoppingCart. The java structure of the two classes is the following:

Customer class:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Customer extends User implements Serializable {

    @OneToOne(mappedBy = "owner", cascade=CascadeType.ALL)
    private ShoppingCart shoppingCart;

    @OneToMany(mappedBy = "customer", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private List<Purchase> purchases;

    public Customer() {
        super();
    }

    public Customer(String username, String email, String password) {
        super(username, email, password);
        this.shoppingCart = new ShoppingCart();
        this.purchases = new ArrayList<>();
    }

    getters and setters

}

ShoppingCart class:

@Entity
public class ShoppingCart implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer shoppingCartId;

    @OneToOne
    @JoinColumn(name = "owner_id")
    private Customer owner;

    @OneToMany(mappedBy = "shoppingCart")
    private List<CartItem> items;

    public ShoppingCart(Customer owner) {
        this.owner = owner;
        this.items = new ArrayList<>();
    }

    public ShoppingCart() {
        this.items = new ArrayList<>();
    }

    getters and setters
}

If needed, this is the User class:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class User implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private Integer userId;
    private String username;
    private String email;
    private String password;

    public User() {
    }

    public User(String username, String email, String password) {
        this.username = username;
        this.email = email;
        this.password = password;
    }

    getters and setters
}

I have configured the Repositories classes in this way:

@Repository
public interface CustomerRepository extends CrudRepository<Customer, Integer> {
}

@Repository
public interface UserRepository extends CrudRepository<User, Integer> {
}

@Repository
public interface ShoppingCartRepository extends CrudRepository<ShoppingCart, Integer> {
}

What I want is simple, once I create a Customer, I also want to create a ShoppingCart tuple inside the database. And it actually works fine, the only problem is that the foreign key of the ShoppingCart related with the Customer is set to null. I just have the shopping_cart_id attribute set to an integer value (correctly).

The code I used to test it is the following:

Customer customer = new Customer("stefanosambruna", "ste23s@hotmail.it", "*******");
customerRepository.save(customer);

Now, I may have put some annotations in the wrong places, but I really don't know which ones. Is it related to the constructors? Or to the @JoinColumn and mappedBy configurations? I read all the Q&As about this topic here on StackOverflow and on some other sources, but I didn't find anything 100% useful. Hope to have given all the necessary details.

Stefano Sambruna
  • 767
  • 2
  • 10
  • 29
  • Please show us a minimal complete verifiable example (https://stackoverflow.com/help/mcve) so that we can help you solve your problem. – gpeche Oct 18 '18 at 13:10
  • Could you please add the code where your entities are saved? – Leviand Oct 18 '18 at 13:11
  • 2
    In the constructor of `Customer` where you initialize the shopping cart you might want to call the `ShoppingCart` constructor where you pass `this` as argument or call `setOwner` with `this` afterwards. – Smutje Oct 18 '18 at 13:55
  • @Smutje is right: In JPA, you have to set the 'foreign keys' yourself before persisting. – JimmyB Oct 18 '18 at 13:58
  • In both cases, if I pass this as an argument of the constructor or I call setOwner outside the constructor, I get an error: nested exception is org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Infinite recursion (StackOverflowError); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: com.job.model.ShoppingCart["owner"]->com.job.model.subjects.Customer["shoppingCart"]-> and so on. But after that error inside the database there is the ShoppingCart \w the correct FK. – Stefano Sambruna Oct 18 '18 at 14:01
  • I don't see where the `ShoppingCart` class does any calls to the `owner` field. – Smutje Oct 18 '18 at 14:04
  • In my question it doesn't, but I have just tried! – Stefano Sambruna Oct 18 '18 at 14:05
  • 1
    Also, I don't see any JSON above so your new error might have something to do with incorrect serialization rather than persistence. – Smutje Oct 18 '18 at 14:05
  • Yeah you are right, it seems that because there is a ShoppingCart inside a Customer and the same Customer inside the ShoppingCart, it bothers the serialisation process making it to loop over it. What do you think? @Smutje – Stefano Sambruna Oct 18 '18 at 14:07
  • I always separate DTO and entity classes because entities might have circular dependencies. – Smutje Oct 18 '18 at 14:09
  • Ok the problem was, as Smutje mentioned, the circular reference introduced by the OneToOne dependency. So I just added the annotation @JsonIgnore on the attribute Customer inside the ShoppingCart class, in order to tell to the JSON parser to break the cyrcle. Now it works fine. More about this [here](https://stackoverflow.com/questions/3325387/infinite-recursion-with-jackson-json-and-hibernate-jpa-issue) – Stefano Sambruna Oct 18 '18 at 15:48

0 Answers0