Skip to content
Advertisement

Problem with Foreign Key in @OneToOne annotation

I have spent a couple of days with a weird problem. There is a plethora of similar posts here in StackOverflow and I have check a lot of them but I was unable to find something similar with this. I have a Human Parent class

import javax.persistence.*;
import java.util.Date;

@Entity(name = "Human")
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Human
{
    @Id
    @Column(name = "human_id", nullable = false)
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private Long id;

    @JsonProperty("name")
    private String name;

    @JsonProperty("date_of_birth")
    private Date dateOfBirth;

    @Embedded
    @JsonProperty("authentication_credential")
    private AuthenticationCredentials authCred;

    // constructors + setter/getters
}

A User child class :

import javax.persistence.*;
import java.util.Date;

@Entity(name = "User")
@Table(name = "end_user")
public class User extends Human
{
    @OneToOne(mappedBy = "user",
              cascade = CascadeType.ALL,
              fetch = FetchType.LAZY,
              optional = false)
    @JsonProperty("contact_numbers")
    private CollectionOfContactMethods contactNumbers;

    @JsonProperty("telephone")
    private String telephone;

    // constructors + setter/getters
 }

and also a CollectionOfContactMethods with composition relationship with the User.

import javax.persistence.*;
import java.util.List;

@Entity(name = "CollectionOfContactMethods")
@Table(name = "collection_of_contact_methods")
public class CollectionOfContactMethods
{
    @Id
    @Column(name = "collection_id", nullable = false)
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private Long id;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "ext_human_id", referencedColumnName = "human_id")
    private User user;

    @JsonProperty("email")
    private String email;

    // constructors + setter/getters
}

The plan, according to the ER diagram is this :

enter image description here

However, what I get at a database level is this :

enter image description here

I appreciate the time you spent. Thanks.

PS : Here is the UserController

@RestController
@RequestMapping("api/v1/user/")
public class UserController
{
    @Autowired
    UserService userService;

    @GetMapping(value = "users")
    Iterable<User> list()
    {
        Iterable<User> retVal = userService.findAll();
        return retVal;
    }

    @RequestMapping(value = "user", method = RequestMethod.POST)
    User create(@RequestBody User user)
    {
        return userService.save(user);
    }

    @RequestMapping(value = "user/{id}",  method = RequestMethod.GET )
    Optional<User> get(@PathVariable Long id)
    {
        return userService.findById(id);
    }
}

and also UserService :

import com.tsakirogf.schedu.model.human.User;
import org.springframework.data.repository.CrudRepository;

public interface UserService extends CrudRepository<User, Long>
{
}

Advertisement

Answer

Since you have a bi-directional relationship between User and CollectionOfContactMethods, the issue might be that CollectionOfContactMethods user is null when you try to create it, hence the null data in the database or the not-null property references a null or transient value : com.tsakirogf.schedu.model.CollectionOfContactMethods.user error. Try the following:

@RequestMapping(value = "user", method = RequestMethod.POST)
User create(@RequestBody User user) {
    CollectionOfContactMethods contactNumbers = user.getContactNumbers();
    contactNumbers.setUser(user);
    user.setContactNumbers(contactNumbers);
    return userService.save(user);
}
User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement