Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » EclipseLink » Persist with secondaryTable from non PK field
Persist with secondaryTable from non PK field [message #1768550] Wed, 19 July 2017 22:25 Go to next message
Mariano Cano is currently offline Mariano CanoFriend
Messages: 3
Registered: December 2014
Junior Member
Hi! I have two tables:

    area (
      id int PK autoincrement
      code varchar UNIQUE IDX
      ...
    )
    
    products (
      id int PK autoincrement
      ...
      area_id int
      ...
    )


I have the secondary table defined in this way:

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


This works fine for for createQuery to get the object. But when I try to persist:


Exception Description: Missing mapping for field [area.id].
Descriptor: RelationalDescriptor( xxx.Product --> [DatabaseTable(products), DatabaseTable(area)])


Basically what I want, is to set the area.id in product.area_id when I write product.setArea("XXX") using the code.

How could I do this? Is it possible?

Edit: bad copy/paste.. sorry

Thanks!

[Updated on: Wed, 19 July 2017 22:29]

Report message to a moderator

Re: Persist with secondaryTable from non PK field [message #1768688 is a reply to message #1768550] Fri, 21 July 2017 14:42 Go to previous messageGo to next message
Mariano Cano is currently offline Mariano CanoFriend
Messages: 3
Registered: December 2014
Junior Member
I finally did it. Now if there is someone that could tell me if what I did is a good/bad practice would be nice. (At least is working now)

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

}

Re: Persist with secondaryTable from non PK field [message #1768706 is a reply to message #1768688] Fri, 21 July 2017 19:07 Go to previous message
Chris Delahunt is currently offline Chris DelahuntFriend
Messages: 1272
Registered: July 2009
Senior Member
This seems very complex for something that doesn't seem to really match what you have in database. If products has a foreign key to Area, it might make sense to treat it as such and create an Area entity, even if it isn't exposed in your model. Something like:

@Entity
class Area (
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
Integer id;
private String code;
...
)

@Entity
public class Product (
@GeneratedValue(strategy=GenerationType.IDENTITY)
Integer id;
@OneToOne(cascade={CascadeType.ALL})
@JoinColumn(name="area_id")
private Area area;
...
public String getArea() {
if (area!=null)
return area.getCode();
return null;
}
public void setArea(String area) {
if (this.area!=null)
this.area = new Area();
this.area.setCode(area);
}
}

This will ensure id generation is used for both rows, be portable to all JPA providers, hide the table details while still giving you the option to use area fields in queries or even in other objects should your business logic change.
Previous Topic:Sharing one column in multiple ForeignKeys
Next Topic:SQL Server session Settings
Goto Forum:
  


Current Time: Tue Nov 21 08:22:51 GMT 2017

Powered by FUDForum. Page generated in 0.01927 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software