简体   繁体   中英

Polymorphic association in static metamodel JPA

I have an entity which contain polymorphic association to few entities. It definition:

@Entity
@Table(name = "notifications")
public class Notification implements java.io.Serializable {

//some fields ...

//Polymorphic association
@Any (metaColumn = @Column(name = "target_type"), fetch = FetchType.LAZY)
@AnyMetaDef(idType = "integer", metaType = "string",
        metaValues = {
        @MetaValue(targetEntity = Task.class, value = "Task"),
        @MetaValue(targetEntity = AdminNote.class, value = "AdminNote"),
        @MetaValue(targetEntity = UserCancelRequest.class, value = "UserCancelRequest"),
        //@MetaValue(targetEntity = TransferInfo.class, value = "TransferInfo"),
        //@MetaValue(targetEntity = NoteSubscription.class, value = "NoteSubscription")
})
@JoinColumn(name = "target_id")
@Getter
@Setter
private NotificationAssociation target;

My polymorphic association represented by interface NotificationAssociation:

public interface NotificationAssociation {
/**
 * Return actual type of associated entity
 * @return one of {@link NotificationTargetType}
 */
String getTargetType();

/**
 * Return associated entity id. Used in queries
 * @return target entity id
 */
Integer getTargetId();
}

And this works. But i need an access to target from Notification class in criteria though static metamodel API. My metamodel:

@StaticMetamodel(Notification.class)
public class Notification_ {
public static volatile SingularAttribute<Notification, Integer> id;
public static volatile SingularAttribute<Notification, Integer>   postedById;
public static volatile SingularAttribute<Notification, Integer> adminId;
public static volatile SingularAttribute<Notification, NotificationAssociation> target;
public static volatile SingularAttribute<Notification, Date> hiddenAt;
public static volatile SingularAttribute<Notification, Date> createdAt;

}

In HQL/JPQL i can get access to it, but in metamodel target is null, and when i get model trough Root#getModel() a target isn't present in attributes list. And my question is can i do so or there is any other solution. Thanks for your help

I'm pretty sure you solved your problem but I recently faced the same issue. And on my case I really needed to use CriteriaAPI since I had some generic processing for creating specifications. Since HQL was not an option for me and we cannot mix HQL with specifications. I fixed this issue by mapping the column twice. Using your example:

@Any (metaColumn = @Column(name = "target_type"), fetch = FetchType.LAZY)
@AnyMetaDef(idType = "integer", metaType = "string",
        metaValues = {
        @MetaValue(targetEntity = Task.class, value = "Task"),
        @MetaValue(targetEntity = AdminNote.class, value = "AdminNote"),
        @MetaValue(targetEntity = UserCancelRequest.class, value = "UserCancelRequest")
})
@JoinColumn(name = "target_id")
@Getter
@Setter
private NotificationAssociation target;

@Column(name = "target_id", insertable = false, updatable = false)
private Integer targetId;

Doing that small tweak the metadata gets generated for targetId field and it becomes available on Criteria API. So then you can do something like:

notificationService.getAll((root, query, cb) -> cb.and(cb.equals(root.get("targetId"), someId), ...))

I hope this helps to anybody that is facing the same issue.

Think I figure it out. An @Any annotation and related to it (@AnyMetadef and other) provides by Hibernate, not JPA. So we can't use JPA Criteria API to manage this kind of relations, but we can use Hibernate Criteria API instead.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM