2

I have the below JSON as input:

{
  "type": "Student",
  "numOfPeople": "1",
  "tenantMembers": [
    {
      "firstName": "Chris",
      "lastName": "C"
    }
  ],
  "tenantDetails": {
    "firstName": "John",
    "lastName": "J",
    "email" "xyz@gmail.com"
  }
}

I want to use this to do a save:

tenantRepo.save(tenant);

This should save the parent "Tenant" and the children "TenantMembers" and "TenantDetails".

But when I do it does with NULL 'tenant_id's in the children. (If I have foreign keys in the DB gives 'tenant_id' can't be null constraint exception)

My question is: Is this possible in Hibernate?

My models:

Parent class:

@Entity
@Table(name = "tenant")
public class Tenant {

@GeneratedValue
@Id
private Long id;

private String type;

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

@OneToMany(mappedBy = "tenant", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<TenantMember> tenantMembers;

@OneToOne(mappedBy = "tenant", cascade = CascadeType.ALL)
private TenantDetails tenantDetails;

TenantMember child class:

@Entity
@Table(name = "tenant_member")
public class TenantMember {
@GeneratedValue
@Id
private Long id;

@ManyToOne
@JoinColumn(name = "tenant_id")
private Tenant tenant;

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

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

TenanatDetails child class:

@Entity
@Table(name="tenant_details")
public class TenantDetails {
@GeneratedValue
@Id
private Long id;

@OneToOne
@JoinColumn(name = "tenant_id")
private Tenant tenant;

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

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

private String email;

EDIT:

Following up Dragan Bozanovic's suggestion, tried using @JsonIdentityInfo for the three tables:

@Entity
@Table(name = "tenant")
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
public class Tenant {


@Entity
@Table(name="tenant_details")
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
public class TenantDetails {


@Entity
@Table(name = "tenant_member")
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
public class TenantMember {

and did the following to save:

@RequestMapping(value = "/set", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public Tenant test(@RequestBody Tenant tenant) {
    Tenant t = new Tenant();
    t.setType(tenant.getType());
    t.setNumOfPeople(tenant.getNumOfPeople());
    tenantRepo.save(t);
    tenant.setId(t.getId());
    tenant.getTenantDetails().setTenant(tenant);
    for(TenantMember member: tenant.getTenantMembers()) {
        member.setTenant(tenant);
    }
    return tenantRepo.save(tenant);
}

Would this be the best approach that is possible?

soufrk
  • 825
  • 1
  • 10
  • 24
kukkuz
  • 41,512
  • 6
  • 59
  • 95

1 Answers1

1

Hibernate does save the children (hence the constraint violation) because of the cascading options you specified, but it does not save the relationship information (join column value) in your case.

TenantMember and TenantDetails are the owners of the association with Tenant (mappedBy attributes in the association annotations in Tenant).

That means that you have to properly update the tenant field in the TenantMember and TenantDetails instances, because Hibernate ignores inverse side of the association when maintaining the relationship.

Dragan Bozanovic
  • 23,102
  • 5
  • 43
  • 110
  • That's good to know, I was trying to make it work.... Thanks. How would you suggest I save the JSON received- i'm confused on that? – kukkuz Apr 21 '16 at 18:30
  • You can either do it manually (iterate over the deserialized objects) or consult the documentation of the framework you use for handling JSON. For example, with Jackson you can do it with `@JsonManagedReference` and `@JsonBackReference`; see [this tutorial](http://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion) for an example. – Dragan Bozanovic Apr 21 '16 at 18:44
  • tried using JsonIdentityInfo, and have appended it to the question... could you please check and give your comments – kukkuz Apr 22 '16 at 12:56
  • This is not related to the original issue that was caused by not setting the value on the owner side of the association. I would recommend you ask a separate question for that. – Dragan Bozanovic Apr 22 '16 at 13:12
  • I was actually following your suggestion in the tutorial that you referred to above.... – kukkuz Apr 22 '16 at 13:41