Persist with secondaryTable from non PK field [message #1768550] |
Wed, 19 July 2017 18:25  |
Eclipse User |
|
|
|
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 18:29] by Moderator
|
|
|
Re: Persist with secondaryTable from non PK field [message #1768688 is a reply to message #1768550] |
Fri, 21 July 2017 10:42   |
Eclipse User |
|
|
|
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 15:07  |
Eclipse User |
|
|
|
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.
|
|
|
Powered by
FUDForum. Page generated in 0.03043 seconds