Search code examples
jpaeclipselink

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!


Solution

  • 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;
    }
    

    }