Francesco
Francesco

Reputation: 1802

unidirectional OneToMany mapping problems

I'm facing some problems with unidirectional onetomany mapping. I got tables Users and Rubrica:

User (
scode double precision NOT NULL,
...
CONSTRAINT utenti_pkey PRIMARY KEY (scode)
)

Rubrica (
id serial NOT NULL,
id_owner integer NOT NULL,
id_contact integer NOT NULL,
CONSTRAINT rubrica_pkey PRIMARY KEY (id ),
CONSTRAINT rubrica_fk01 FOREIGN KEY (id_owner)
  REFERENCES users (scode) MATCH SIMPLE
  ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT rubrica_fk02 FOREIGN KEY (id_contact)
  REFERENCES users (scode) MATCH SIMPLE
  ON UPDATE NO ACTION ON DELETE NO ACTION
)

Don't mind about Users double PKey. It's a customer's table and I can't modify it. Rubrica store relation between its owner, a User, and contacts, a set of User too. User is mapped as follow:

@SuppressWarnings("serial")
@Entity
@Table(name = "utenti", schema = "public")
public class User implements Serializable {
  @Id
  @Column(name = "scode", unique = true, nullable = false)
  private Integer scode;
...
}

Ok. Here is when problems come. If I map Rubrica like this:

public class Rubrica2 implements Serializable {
  @Id
  @Column(name = "id", nullable = false, unique = true)
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Integer id;

  @OneToOne(fetch = FetchType.EAGER)
  @JoinColumn(name = "id_owner", nullable = false, unique = true, referencedColumnName = "scode")
  private User owner;

  @OneToMany(fetch = FetchType.EAGER)
  @JoinColumn(name = "id_contact", nullable = false, updatable = false, insertable = true, referencedColumnName = "scode")
  private Set<User> relations = new HashSet<User>();
  ...
}

JBoss gave me this exception at deploy:

Caused by: org.hibernate.MappingException: Unable to find column with logical name: scode in org.hibernate.mapping.Table(public.rubrica) and its related

supertables and secondary tables

If I map Rubrica this way:

public class Rubrica2 implements Serializable {
  @Id
  @Column(name = "id", nullable = false, unique = true)
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Integer id;

  @OneToOne(fetch = FetchType.EAGER)
  @JoinColumn(name = "id_owner", nullable = false, unique = true, referencedColumnName = "scode")
  private User owner;

  @OneToMany(fetch = FetchType.EAGER, mappedBy = "scode")
  private Set<User> relations = new HashSet<User>();
  ...
}

I got bad behavior at runtime. If I run this code

r = new Rubrica2();
q2.setParameter("id", ownerID);
User owner = (User) q2.getSingleResult();
r.setOwner(owner);
q2.setParameter("id", contactID);
User u = (User) q2.getSingleResult();
r.getRelations().add(u);
entityManager.persist(r);

I got this exception:

Hibernate: insert into public.rubrica (id_owner) values (?)
11:08:19,440 DEBUG [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (EJB default - 7) 
  ERROR: null values in column "id_contact" violates not-null constraint [n/a]: org.postgresql.util.PSQLException: 
    ERROR: null values in column "id_contact" violates not-null constraint

I follow theory indicated here about onetomany unidirectional. I'm using JPA2.0, Hibernate4 (as provided by JBoss7.1.1.Final) and PostgresSQL.

Upvotes: 1

Views: 1380

Answers (1)

JB Nizet
JB Nizet

Reputation: 692191

This mapping, or the database design, makes no sense. If you want one Rubrica to have many contacts, you can't have a foreign key to the relation in the rubrica table. A foreign key can only reference one contact, not many.

To map such a one-to-many association, you would need a foreign key in user to rubrica (all the users having the same rubrica_id would be the contacts of this rubrica), or a join table between both tables.

Upvotes: 1

Related Questions