JPA Specification for Many to One mapping between child and parent entity - spring-data-jpa

I have two entities Parent Entity name is UserEntity and Child Entity name is PermissionEntity Relationship between entity is oneToMany. The Child table has company entity relation is Many to one
User Entity ---oneToMany--permissionEntity
permissionEntity--ManyToOne--CompanyEntity
In JPA specification I have written class for root
How to filter based on CompanyId from CompanyEntity
below snippet of code
return Specification { root, _, builder ->
val predicates = mutableListOf()
companyID?.let {
val join: Join<UserDetailEntity, PartnerPermissionEntity> = root.join("the1permission",JoinType.LEFT) //, JoinType.INNER
val predicate = builder.equal(
join.get("company"), ---error at this line
it,
)
predicates.add(predicate)
}

Related

Union from two different entities but same viewmodel class

I have 2 different entities: EntityA and EntityB.
All fields are Strings.
I have a common ViewModel class: MyViewModel.
I have 2 queries:
var query1 = from a in EntityA select new MyViewModel { field1=a.somefield1, field2= a.somefield2 };
var query2 = from a in EntityB select new MyViewModel { field1=a.somefield3, field2="String Constant" };
EntityA and EntityB are different but my 2 queries gives us the same result: An IQueryable of MyViewModel.
So i am trying to make an union:
var query3 = query1.Union(query2);
I get this error:
"Unable to translate set operation when matching columns on both sides
have different store types".
This is because EF does not put the same datatype for my string constant and a.somefield2. somefield2 is a varchar(100), but "String Constant" is a string and i don't know how EF translate it.
Thanks
The dotnet version is .Net5 and i am using Microsoft.EntityFramework.Core.SqlServer 5.0.10

JPA OneToMany duplicate child

I am trying to implement a OneToMany relationship and having a really hard time in selecting the child records.
For example: Parent P1 has 3 Child entities and Parent P2 has 2 Child entities, say
P1 has C1,C2,C3
P2 has C4,C6
But code below returns
P1 has C1,C1,C1
P2 has C1,C1
Interestingly the number of child entities is correct, but the data itself is just duplicate of the first record. I tried setting distinct but that doesn't seem to help.
CriteriaBuilder criteriaBuilder = db2EntityManager.getCriteriaBuilder();
CriteriaQuery<Parent> searchQuery = criteriaBuilder.createQuery(Parent.class);
Root<Parent> aRoot = searchQuery.from(Parent.class);
//Constructing list of parameters
List<Predicate> predicates = new ArrayList<>();
//Adding predicates in case of parameter not being null
predicates.add(criteriaBuilder.equal(aRoot.get("a"), "A"));
predicates.add(criteriaBuilder.equal(aRoot.get("b"), "B"));
predicates.add(criteriaBuilder.equal(aRoot.get("c"), "C"));
//query itself
searchQuery.select(aRoot).where(predicates.toArray(new Predicate[]{})).distinct(true);
TypedQuery<Parent> query = db2EntityManager.createQuery(searchQuery);
parentEntities = query.getResultList();
Turns out the issue was with the Primary Key in the Child entity. The composite key was not returning unique records.

Does #OneToOne imply uniqueness?

I annotated my fields with only #OneToOne and when I check the database (generated using liquibase) saw that there are unique constraints on database columns.
Does this mean #OneToOne implies uniqueness just by itself, eg. one Building can only be in one city, and no other Buildings can be in the same city?
What do I do when I want to tell that there may be other other buildings in the same city?
add #JoinColumn(unique = false),
only use #JoinColumn(unique = false) without #oneToOne,
or use #ManyToOne?
or leave it without any annotations?
I don't want to put a Buildings field in the city class, because I wouldn't ever call city.getBuildings();. Does any of the below require a bidirectional reference?
class Building {
#OneToOne(optional = false)
City city;
}
class Building {
#OneToOne(optional = false)
#JoinColumn(unique = false)
City city;
}
class Building {
#JoinColumn(unique = true)
City city;
}
class Building {
#ManyToOne
City city;
}
The JPA specification says that for a bidirectional OneToOne relationship (2.10.1 Bidirectional OneToOne Relationships):
Assuming that:
Entity A references a single instance of Entity B.
Entity B references a single instance of Entity A.
Entity A is specified as the owner of the relationship.
The following mapping defaults apply:
Entity A is mapped to a table named A.
Entity B is mapped to a table named B.
Table A contains a foreign key to table B. [...] The foreign key column has the same type as the primary key of table B and there is a unique key constraint on it.
In case of unidirectional OneToOne relationship (2.10.3.1 Unidirectional OneToOne Relationships):
The following mapping defaults apply:
Entity A is mapped to a table named A.
Entity B is mapped to a table named B.
Table A contains a foreign key to table B. [...] The foreign key column has the same type as the primary key of table B and there is a unique key constraint on it.
If you have a City-Building relationship, then for any reasonable city it would be a OneToMany/ManyToOne relationship, since a given city can have multiple buildings, but a given building can be only in one city.

JPA annotation for mapped entity with values based on the root entity?

I'm trying to annotate my JPA-Entity. In the entity I want to map another Entity which should be loaded by values of the root entity.
Example:
Entity A has the fields key1 & key2.
I want to map Entity B which should be loaded by the filter b.key1 = a.key1 & b2.key2 = a.key2
Can anyone help?
I got the solution. I just used #ManyToOne and #JoinColumns:
#ManyToOne
#JoinColumns(
{
#JoinColumn(name="key1", referencedColumnName="refKey1"),
#JoinColumn(name="key2", referencedColumnName="refKey2")
}
)
private EntityB entityB;

Entity Framework atypical 1-[0..1] -- model-only Association -- EF LINQ select possibilities

Suppose the following tables
ParentEntities
ParentID
ChildEntities
ChildID
ParentID
These tables do not have a FK defined in the schema.
In EF designer, after generating from DB, I add an association:
- Parent Multiplicity: 1
- Child Multiplicity: 0 or 1
When I build, I get the error: "Error 3027: No mapping specified for the following EntitySet/AssociationSet - ParentChild"
But if I try to configure table mapping for the association like this..
Maps to ChildEntities
Parent
ParentID <-> ParentID (parent entity prop <-> child table column)
Child
ChildID <-> ChildID (child entity prop <-> child table column)
.. I get this: Error 3007: Problem in mapping fragments starting at lines xxx, xxx: Column(s) [ParentID] are being mapped in both fragments to different conceptual side properties.
Why this is an error doesn't make sense. Limitation of the current implementation?
[EDIT 1]
I'm able to make this work by creating a 1-N association. That's not ideal, but it works just the same, just have to add a read-only child property in a partial:
public partial class Parent
{
public Child Child { get { return Childs.Any() ? null : Childs.First(); } }
}
This seems like the best solution for me. I had to add a FK to the database to get EF to generate the association and navigation property, but once it was added I was able to remove the FK, and further updates to the model from the DB did not remove the association or Navigation properties.
[EDIT 2]
As I was investigating how to work around not caring about the association being modeled in EF, I ran into another issue. Instead of the read-only Child property I made it normal ..
public partial class Parent
{
public Child Child { get; set; }
}
.. but now I need a way to materialize that from the query:
var query = from parents in context.Parents
// pointless join given select
join child in context.Childs
on parents.ParentID equals child.ParentID
select parents;
I can select an anonymous type ..
// step 1
var query = from parents in context.Parents
join child in context.Childs
on parents.ParentID equals child.ParentID
select new { Parent = parents, Child = child };
.. but then I've got to consume more cycles getting that into my entity:
// step 2
var results = query.Select(x => {
var parent = x.Parent;
parent.Child = x.Child;
return parent; });
Is there a better/streamlined way to do this from the query select so the EF materializer can do it from the get-go? If not, then I'll resort to Edit 1 methodology ..
Ef Code first requires 1->0..1 relationships for the Child to have the same primary key.
Maybe this a similar restriction In the modeler in this circumstance.
ParentId (Key) required in Both tables.
I have never tried adding such relationships in designer afterwords in DB first.
EDIT: to match your EDIT2:
I would stay on the direction . Use Navigation properties to get from Join back to original class A and B.
query = context.Set<JoinTable>.Where(Jt=>Jt.NavA.Id == ClassAId
&& Jt.navB.Id == ClassBId)
use a select if your need entries returned from either ClassA or ClassB.