Filtering a list in Objectify using Ref - eclipse

How do i filter a list of an entity in Objectify which has Ref to another entity. The list should be filtered out based on a String field in the Ref entity.
public class AccountEntity extends BaseEntity {
#Index
private String accountName;
private String accountNo;
private String description;
private Integer displayOrderNo;
private Boolean contra = false;
private AccountingAccountType accountType;
#Index
private Ref<AccountGroupEntity> accountGroup;
#Ignore
private List<AccountEntryEntity> accountLedgerEntries;
public AccountEntity() {
}
this is ref entity
filter code

A ref is a key, so you can filter the key by passing in either a Key, Key<>, Ref<> or #Entity pojo.
You cannot however filter on a property of the entity that the key points to. To do this you'll need to denormalise that property into a separate indexed list in this entity, or create a lookup entity, similar to a join table.

Related

JPA Criteria API join on 3 tables and some null elements

I have one parent entity that has two child entities as attributes.
I want to select all elements from the parent entity that have EITHER a childOne with a given parameter as personal attribute OR childTwo with that same given parameter as personal attribute.
Here are my three classes simplified:
The Parent Object:
#Entity
public class ParentObject {
#Id
private int id;
private int fkChildOne;
private int fkChildTwo;
#ManyToOne
#JoinColumn(name = "fk_child_one_id", referencedColumnName =
"child_one_id")
private ChildOne childOne;
#ManyToOne
#JoinColumn(name = "fk_child_one_id", referencedColumnName =
"child_one_id")
private ChildTwo childTwo;
// getters and setters
}
The Child One Object:
#Entity
public class ChildOne {
#Id
private int childOneId;
private String nameChildOne;
#OneToMany
#JoinColumn(name = "fk_child_one_id")
private List<ParentObject> parents;
// getters and setters
}
The Child Two Object:
#Entity
public class ChildTwo {
#Id
private int childOneId;
private String nameChildTwo;
#OneToMany
#JoinColumn(name = "fk_child_two_id")
private List<ParentObject> parents;
// getters and setters
}
The Specs Class:
public static Specification<ParentObject> checkName(String name) {
return Specifications.where(
(root, query, builder) -> {
final Join<ParentObject, ChildOne> joinchildOne =
root.join("childOne");
final Join<ParentObject, ChildTwo > joinchildTwo =
root.join("childTwo");
return builder.or(
builder.equal(joinchildOne .get("nameChildOne"), name),
builder.equal(joinchildTwo .get("nameChildTwo"), name)
);
}
);
}
When this spec is called in my service, I get no results. However, if I comment out one of the two joins and the corresponding Predicate in my builder.or method, then I get some results but they obviously don't match what I'm looking for, which is to select every ParentObject that have either ChildOne with that parameter or ChildTwo with that paramater.
Any clue what's wrong with the code ?
Finally got the solution : to fetch all the corresponding results, I had to add the type of the join which would be left join, since I wanted to fetch all ParentObjects regardless of owning childOne or ChildTwo objects.
final Join<ParentObject, ChildOne> joinchildOne =
root.join("childOne", JoinType.LEFT);
final Join<ParentObject, ChildTwo > joinchildTwo =
root.join("childTwo", JoinType.LEFT);
Great, now you have to choose if you need to join or fetch.To optimize the query and the memory, you should establish the relations as Lazy (#ManyToMany (fetch = FetchType.LAZY)), so you will only bring the objects that you demand.
The main difference is that Join defines the crossing of tables in a variable and allows you to use it, to extract certain fields in the select clause, for example, on the other hand, fetch makes it feed all the objects of that property. On your example,
a select from parent with join of children (once the relation is set to lazy) would only bring initialized objects of type parent, however if you perform a fetch, it would bring the parent and child objects initialized.
Another modification I would make is to change the type of the identifier to non-primitive, so that it accepts null values, necessary for insertion using sequences

Joining two entities where both have composite primary key, and we need to join using part of primary key using spring data jpa

I have two entities which has separate composite primary keys, Example :-
#Entity
public class Payment
{
#EmbeddedId
private PaymentPK pk1;
private BigInteger amount;
private String countryCode;
}
#Embeddable
public class PaymentPK implements Serializable {
private Long transactionId;
private String type;
}
#Entity
public class tax
{
#EmbeddedId
private TaxPK pk2;
private BigInteger amount;
private String countryCode;
}
#Embeddable
public class TaxPK implements Serializable {
private Long transactionId;
private String taxType;
}
I want to add relationship #ManyToOne, where every payment transaction can have multiple taxes applied to it. The problem here is both entities have different PK, So join on FK is not working(As per my understanding of JPA it allows join on composite key not on part of it). Please help me how to achieve it.I want join based on transactionId attribute.

Mapping POJOs and Using Reference in MongoDB using Morphia

I have two model classes. One is Company.java, another is HumanResource.java.
Company.java
#Entity("companies")
public class Company {
#Id
private ObjectId id = new ObjectId();
private String companyName;
private String emailAddress;
private String pictureUrl;
#Reference
private List<HumanResource> humanResources;
...
HumanResource.java
#Entity("humanresources")
public class HumanResource {
#Id
private ObjectId id = new ObjectId();
private String firstName;
private String lastName;
private String emailAddress;
#Reference
private Company company;
...
What I want to achieve is when I save a list of companies to datastore, related list of human resources documents should be inserted automatically.
In addition, I declared
#Id
private ObjectId id = new ObjectId();
in every model class. Is it a good way or should I change it ?
Morphia will not call save() on those references. You must call save() on the instances you want to persist. You can pass in a list of instances so you needn't loop, necessarily, but each instance needs to get passed in explicitly.

Hibernate Search Tuple Queries

I have an entity Message with a one-to-many relation to an entity Header. How can I create a tuple based search query like
(message.headerKey="foo" and message.headerValue="123") and
(message.headerKey="bar" and message.headerValue="456")
My current logic would also match when I swap the header values in my search criteria
(message.headerKey="foo" and message.headerValue="456") and
(message.headerKey="bar" and message.headerValue="123")
How can I do a tuple based query using the Hibernate Search API?
This is my Message Entity:
#Entity
#Table(name="MESSAGE")
#Indexed
public class MessageEntity implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="id")
private Long id;
#Column(name="message_timestamp")
private Date timestamp;
#Column(name="payload")
#Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO)
private String payload;
#OneToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE }, mappedBy = "message")
#IndexedEmbedded
private List<HeaderEntity> headers;
// Getters and Setters
}
This is my Header Entity:
#Entity
#Table(name="HEADER")
public class HeaderEntity implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
#Column(name="header_key")
#Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO)
private String headerKey;
#Column(name="header_value")
Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO)
private String headerValue;
#ManyToOne(cascade=CascadeType.ALL)
#JoinColumn(name="message_id")
private MessageEntity message;
// Getters and Setters
}
This is my search logic:
public List<MessageEntity> search(Header[] headers) {
FullTextEntityManager fullTextEntityManager = org.hibernate.search.jpa.Search.getFullTextEntityManager(mgr);
QueryBuilder qb = fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity(MessageEntity.class).get();
TermMatchingContext onFieldKey = qb.keyword().onField("headers.headerKey");
TermMatchingContext onFieldValue = qb.keyword().onField("headers.headerValue");
BooleanJunction<BooleanJunction> bool = qb.bool();
org.apache.lucene.search.Query query = null;
for (Header header : headers) {
bool.must(onFieldKey.matching(header.getKey()).createQuery());
bool.must(onFieldValue.matching(header.getValue()).createQuery());
}
query = bool.createQuery();
FullTextQuery persistenceQuery = fullTextEntityManager.createFullTextQuery(query, MessageEntity.class);
persistenceQuery.setMaxResults(10);
return persistenceQuery.getResultList();
}
Your approach will indeed not work. The problem is that Lucene is a flat data structure, in particular associations (embedded entities) are just "added" to the Lucene Document of the owning entity. In your case the MessageEntity document will contain two fields per headerKey respectively headerValue. Once with "foo" and "bar" as value and56" as values. once with "123" and "456" as values. There is no notion that two of these values are acutally a pair.
One potential solution is to create a unique field/value pair. Using a custom class bridge you could create a "keyValueField" containing header key and value as concatenated value. In your query you would then target this field using concatenated query parameters.

Cannot use an #IdClass attribute for a #ManyToOne relationship

I have a Gfh_i18n entity, with a composite key (#IdClass):
#Entity #IdClass(es.caib.gesma.petcom.data.entity.id.Gfh_i18n_id.class)
public class Gfh_i18n implements Serializable {
#Id #Column(length=10, nullable = false)
private String localeId = null;
#Id <-- This is the attribute causing issues
private Gfh gfh = null;
....
}
And the id class
public class Gfh_i18n_id implements Serializable {
private String localeId = null;
private Gfh gfh = null;
...
}
As this is written, this works. The issue is that I also have a Gfh class which will have a #OneToMany relationship to Gfh_i18n:
#OneToMany(mappedBy="gfh")
#MapKey(name="localeId")
private Map<String, Gfh_i18n> descriptions = null;
Using Eclipse Dali, this gives me the following error:
In attribute 'descriptions', the "mapped by" attribute 'gfh' has an invalid mapping type for this relationship.
If I just try to do, in Gfh_1i8n
#Id #ManyToOne
private Gfh gfh = null;
it solves the previous error but gives one in Gfh_i18n, stating that
The attribute matching the ID class attribute gfh does not have the correct type es.caib.gesma.petcom.data.entity.Gfh
This question is similar to mine, but I do not fully understand why I should be using #EmbeddedId (or if there is some way to use #IdClass with #ManyToOne).
I am using JPA 2.0 over Hibernate (JBoss 6.1)
Any ideas? Thanks in advance.
You are dealing with a "derived identity" (described in the JPA 2.0 spec, section 2.4.1).
You need to change your ID class so the field corresponding to the "parent" entity field in the "child" entity (in your case gfh) has a type that corresponds to either the "parent" entity's single #Id field (e.g. String) or, if the "parent" entity uses an IdClass, the IdClass (e.g. Gfh_id).
In Gfh_1i8n, you should declare gfh like this:
#Id #ManyToOne
private Gfh gfh = null;
Assuming GFH has a single #Id field of type String, your ID class should look like this:
public class Gfh_i18n_id implements Serializable {
private String localeId = null;
private String gfh = null;
...
}