0

I have a LoginCredential class :

public class LoginCredential {
    @Id @GeneratedValue Long userID;
    String eMail;
    String passwordHash;
    @OneToOne(mappedBy = "loginCredential", fetch = FetchType.LAZY)
    User user;
    LoginCredential(){}
    public LoginCredential(String eMail, String passwordHash, User user) 
    {
        this.eMail = eMail;
        this.passwordHash = passwordHash;
        this.user = user;
    }
}

Then I have User class :

public class User {
    @Id @GeneratedValue Long userID;
    @OneToOne(fetch = FetchType.LAZY,targetEntity = LoginCredential.class)
    @JoinColumn(name = "userID",referencedColumnName = "userID")
    @JsonIgnore
    private LoginCredential loginCredential;
    public User(){}
    public User(String eMail)
    {
          this.eMail=eMail;
    }
    public User(String eMail, LoginCredential loginCredential) {
        this.eMail = eMail;
        this.loginCredential = loginCredential;
    }
}

In my system, first of all an instance of LoginCredential gets created.

But for me the problem is after I create that instance, the user field remains null.

How to resolve this?

As they are One to one mapped, is there other way(s) of doing it?

I have tried this : {"email":"test@gmail.com","passwordHash":"a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3","user":{"userID":801,"email":"test@gmail.com"}}

The method I'm using in front end, in my react.js application :

createUserAndCredential = () => {

  var xhr = new XMLHttpRequest();
  xhr.open('POST', 'http://localhost:8080/login/');
  xhr.setRequestHeader("Content-Type", "application/json");
  xhr.send(JSON.stringify({
    email: this.state.email,
    passwordHash: this.state.passwordHash
  }));
  let that = this;
  xhr.onreadystatechange = function() {
    if (this.readyState === 4 && this.status === 200) {
      console.log(this.responseText);
      /*
      console.log(this.responseText);
      console.log(that.state.newLoginCredential);
      */

      that.state.newLoginCredential = this.responseText.toString();


      var xhr1 = new XMLHttpRequest();
      xhr1.open('POST', 'http://localhost:8080/user/');
      xhr1.setRequestHeader("Content-Type", "application/json");
      console.log(that.state.newLoginCredential);

      let user = JSON.stringify({
        email: that.state.email,
        loginCredential: JSON.parse(that.state.newLoginCredential)
      });

      //console.log(loginCredential);

      xhr1.send(user);

    } else if (this.readyState !== 4 && this.status !== 200) {
      console.log(this.status);
    }
  };
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Which gives me this warning :

Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot construct instance of com.mua.cse616.Model.LoginCredential (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('{"email":"t7@gmail.com","passwordHash":"a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3"}'); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of com.mua.cse616.Model.LoginCredential (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('{"email":"t7@gmail.com","passwordHash":"a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3"}') at [Source: (PushbackInputStream); line: 1, column: 43] (through reference chain: com.mua.cse616.Model.User["loginCredential"])]

Andronicus
  • 25,419
  • 17
  • 47
  • 88
Maifee Ul Asad
  • 3,992
  • 6
  • 38
  • 86

1 Answers1

3

Since mapping is on the side of User (mappedBy resides there), you would have to save it to see the changes populated to LoginCredential. But you can define the changes in parent to cascage to child:

@OneToOne(mappedBy = "loginCredential", fetch = FetchType.LAZY, cascade = CascadeType.ALL)

Or if you don't want to cascade everything (for example removal):

@OneToOne(mappedBy = "loginCredential", fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
Andronicus
  • 25,419
  • 17
  • 47
  • 88
  • still the `user` field is `null`. here : `{"userID":993,"passwordHash":"a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3","user":null, "email":"t7@gmail.com"}]` – Maifee Ul Asad Sep 24 '19 at 01:30
  • I have edited the question and added the code I'm using to create this instances, can you please see it. – Maifee Ul Asad Sep 24 '19 at 01:35