• No se han encontrado resultados

Capítulo 1: Revisión de Literatura

1.4 Uso de tecnología en la modelación matemática

1.4.4 Aprendizaje basado en retos como estrategia para el aprendizaje activo

@OneToMany @JoinTable (

name="EMP_PHONE"

joinColumns={ @JoinColumn(name="EMP_ID", referencedColumnName="EMP_ID") }

inverseJoinColumns={ @JoinColumn(name="PHONE_ID", referencedColumnName="PHONE_ID") }

)

private List<Phone> phones;

...

}

Example of a OneToMany relationship XML

<entity name="Employee" class="org.acme.Employee" access="FIELD">

<attributes>

<id name="id"/>

<one-to-many name="phones" mapped-by="owner"/>

</attributes>

</entity>

Note this @OneToMany mapping requires an inverse @ManyToOne mapping to be complete, see ManyToOne.

Getters and Setters

As the relationship is bi-directional so as the application updates one side of the relationship, the other side should also get updated, and be in synch. In JPA, as in Java in general it is the responsibility of the application, or the object model to maintain relationships. If your application adds to one side of a relationship, then it must add to the other side.

This can be resolved through add or set methods in the object model that handle both sides of the relationships, so the application code does not need to worry about it. There are two ways to go about this, you can either only add the relationship maintenance code to one side of the relationship, and only use the setter from one side (such as making the other side protected), or add it to both sides and ensure you avoid a infinite loop.

For example:

public class Employee { private List phones;

...

public void addPhone(Phone phone) { this.phones.add(phone);

if (phone.getOwner() != this) { phone.setOwner(this);

} } ...

}

public class Phone {

private Employee owner;

...

public void setOwner(Employee employee) { this.owner = employee;

if (!employee.getPhones().contains(this)) { employee.getPhones().add(this);

} } ...

}

Some expect the JPA provider to have magic that automatically maintains relationships.

This was actually part of the EJB CMP 2 specification. However the issue is if the objects are detached or serialized to another VM, or new objects are related before being managed, or the object model is used outside the scope of JPA, then the magic is gone, and the application is left figuring things out, so in general it may be better to add the code to the object model. However some JPA providers do have support for automatically maintaining relationships.

In some cases it is undesirable to instantiate a large collection when adding a child object.

One solution is to not map the bi-directional relationship, and instead query for it as required. Also some JPA provides optimize their lazy collection objects to handle this case, so you can still add to the collection without instantiating it.

Example of a OneToMany using a JoinTable XML

<entity name="Employee" class="org.acme.Employee" access="FIELD">

<attributes>

<id name="id">

<column name="EMP_ID"/>

</id>

<one-to-many name="phones">

<join-table name="EMP_PHONE">

<join-column name="EMP_ID" referenced-column-name="EMP_ID"/>

<inverse-join-column name="PHONE_ID" referenced-column-name="PHONE_ID"/>

</join-table>

</one-to-many>

</attributes>

</entity>

See Also

• Relationships

• Cascading

• Lazy Fetching

• Target Entity

• Collections

• Maps

• Join Fetching

• Batch Reading

• Common Problems

• ManyToOne

• ManyToMany

Common Problems

Object not in collection after refresh.

See Object corruption.

Advanced

Undirectional OneToMany, No Inverse ManyToOne, No Join Table (JPA 2.0)

JPA 1.0 does not support a unidirectional OneToMany relationship without a JoinTable. JPA 2.0 will have support for a unidirectional OneToMany. In JPA 2.0 a JoinColumn can be used on a OneToMany to define the foreign key, some JPA providers may support this already.

The main issue with an unidirectional OneToMany is that the foreign key is owned by the target object's table, so if the target object has no knowledge of this foreign key, inserting and updating the value is difficult. In a unidirectional OneToMany the source object take ownership of the foreign key field, and is responsible for updating its value.

The target object in a unidirectional OneToMany is an independent object, so it should not rely on the foreign key in any way, i.e. the foreign key cannot be part of its primary key, nor generally have a not null constraint on it. You can model a collection of objects where the target has no foreign key mapped, but uses it as its primary key, or has no primary key using a Embeddable collection mapping, see Embeddable Collections.

If your JPA provider does not support unidirectional OneToMany relationships, then you will need to either add a back reference ManyToOne or a JoinTable. In general it is best to use a JoinTable if you truely want to model a unidirectional OneToMany on the database.

There are some creative workarounds to defining a unidirectional OneToMany. One is to map it using a JoinTable, but make the target table the JoinTable. This will cause an extra join, but work for the most part for reads, writes of coarse will not work correctly, so this is only a read-only solution and a hacky one at that.

Example of a JPA 2.0 unidirectional OneToMany relationship