Mariano L
Mariano L

Reputation: 1879

Linking two object by code (not ID) using Eclipselink JPA

i have two tables:

area (
  id int PK autoincrement
  code varchar
)

products (
  id int PK autoincrement
  area_id int
)

And the objets are defined like this:

class Product {
    ...
    @JoinColumn(name = "area_id", referencedColumnName = "id")
    @ManyToOne
    @Expose
    private Area area;
    ...    
}

This works fine but I want that area to be a String with the code used in the table area column code.

class Product {
    ...
    ???
    private String area;
    ...    
}

What should be the annotations to make this work?

Thanks!

Upvotes: 1

Views: 134

Answers (2)

Mariano L
Mariano L

Reputation: 1879

If there is some poor soul with the same problem, here is how I did it:

Using transformers. So the field area is defined like this:

@Transformation(fetch = FetchType.EAGER, optional = false)
@ReadTransformer(transformerClass = AreaAttributeTransformer.class)
@WriteTransformers({
        @WriteTransformer(
                transformerClass = AreaFieldTransformer.class,
                column = @Column(name = "area_id", nullable = false))
})
@Expose
private String area;

Then those clases work like this:

AreaAttributeTransformer

public class AreaAttributeTransformer implements AttributeTransformer {

private AbstractTransformationMapping mapping;

@Override
public void initialize(AbstractTransformationMapping abstractTransformationMapping) {
    this.mapping = abstractTransformationMapping;
}


@Override
public Object buildAttributeValue(Record record, Object o, Session session) {
    for (DatabaseField field : mapping.getFields()) {
        if (field.getName().contains("area_id")) {

            EntityManager em = MyEntityManagerFactory.getENTITY_MANAGER_FACTORY().createEntityManager();
            List results = em.createNamedQuery("Areas.findById")
                    .setParameter("id", record.get(field))
                    .getResultList();
            if (results.size() > 0)
                return ((Area) results.get(0)).getCode();
        }
    }
    return null;
}

}

AreaFieldTransformer

public class AreaFieldTransformer implements  FieldTransformer {

private AbstractTransformationMapping mapping;

@Override
public void initialize(AbstractTransformationMapping abstractTransformationMapping) {
    this.mapping = abstractTransformationMapping;
}

@Override
public Object buildFieldValue(Object o, String s, Session session) {
    if (o instanceof RouSub) {
        EntityManager em = MyEntityManagerFactory.getENTITY_MANAGER_FACTORY().createEntityManager();
        List results = em.createNamedQuery("Area.findByCode")
                .setParameter("area", ((Area) o).getCode())
                .getResultList();
        if (results.size() > 0)
            return ((Area)results.get(0)).getId();
    }
    return null;
}

}

Upvotes: 0

Oleksandr Lykhonosov
Oleksandr Lykhonosov

Reputation: 1388

Try to use a combination of @SecondaryTable and @Column annotations. Something like this:

@Entity    
@SecondaryTable(name="area", pkJoinColumns=@PrimaryKeyJoinColumn(name="id", referencedColumnName="area_id"))
class Product {
    ...
    @Column(name="code", table = "area")
    private String code;
    ...
}

Upvotes: 2

Related Questions