I have three entities, for example A, B, C. Entity A is parent for B, with inheritance type joined. Entity B aggregates entity C with ManyToOne relationship.
Structure looks like next:
#Entity
#Inheritance(strategy = InheritanceType.JOINED)
class A {
String str;
String cStr;
}
#Entity
class B extends A {
#ManyToOne
C c;
}
#Entity
class C {
String str;
}
I don't know if it is possible at all on entity level but, I need to link value of str from C to the filed A.cStr. How it should looks like: I create entity B with populated value of c, store it and value from C.str is populating into filed A.cStr. And when I fetch A from datebase I can see A.cStr with same value as C.str has.
No, it's not possible. All you need to do to get the C string from A is to implement a method and override it in B:
in A:
public String getCString() {
return null;
}
in B:
#Override
public String getCString() {
return c.getStr();
}
Of course, the instances of A that are not B instances won't have any CString.
Related
I have Class A contains List of Class B that contains List of Class C
so how I would achieve this in ObjectBox ? how do I store it?
in the pic below you can see that I have BasicInfo Class Contains Data class and so on....
I put #Entinty annotation on BasicInfo class and after generating the models class D doesn't show up in the
objectbox.g.dart file as it's on of BasicInfo properties
ModelEntity(
id: const IdUid(1, 3501283007979667013),
name: 'BasicInfo',
lastPropertyId: const IdUid(1, 2073579066569957521),
flags: 0,
properties: <ModelProperty>[
ModelProperty(
id: const IdUid(1, 2073579066569957521),
name: 'id',
type: 6,
flags: 1)
],
relations: <ModelRelation>[],
backlinks: <ModelBacklink>[])
If you're saying Class A contains a List of Class B, then their relationship isn't a subclass/superclass but it's a standard composition. I understand your definition looks somewhat like this:
class A {
List<B> bs;
}
class B {
List<C> cs;
}
class C {}
And in order to use it in ObjectBox, you can define them as relations, either a standalone ToMany relation, or a ToOne relation with a backlink - depends on what better describes your data, you can achieve the same with both.
1st alternative - using ToMany
ToMany relation stores the info in a separate "table" of IDs, like: A.id <--> B.id and another one between B.id <--> C.id.
#Entity()
class A {
int id;
final bs = ToMany<B>();
}
#Entity()
class B {
int id;
final cs = ToMany<C>;
}
#Entity()
class C {
int id;
}
2nd alternative - using ToOne with a backlink
ToOne relation can achieve the same in your case and the relatin info is actually stored on the object itself as a single ID, i.e. there's a hidden int B.classAId field that and you can get all Bs for a class A instance by looking for those Bs pointing to this A. This is done behind the scenes by a ToMany<> with a Backlink() annotation.
#Entity()
class A {
int id;
#Backlink()
final bs = ToMany<B>();
}
#Entity()
class B {
int id;
final a = ToOne<A>;
#Backlink()
final cs = ToMany<C>;
}
#Entity()
class C {
int id;
final b = ToOne<B>;
}
we have
class A{
#id
int id;
List <B> bs;
}
where
class B{
String prId;
int pr;
}
i need a way to get list of B without duplication using prId.
so please suggest a way to get
[
{
prId: "18876",
pr: 1228876
},
{
prId: "123",
pr: 1228876
}
]
2 solutions (or more)
change List<B> bs; to Set<B> bs; and make sure class B has and equal/hashcode method base only on the prId
Since B is and embedded list of document (B does not have its on collection), there is no id created when you save A, you can generate a mongo id (ObjectId) on save of A by yourself like this
class B{
#Id
String prId;
int pr;
// get set
}
B b = new B();
b.setPrId(ObjectId.get().toString());
then by retreiving A all Bs are suppose to be unique
Is it possible to have a custom collection type as a backing field in Entity Framework Core 3?
I have an entity A that has a OwnsMany relationship with an entity B. Since there are many business rules that needed to be checked before adding B to A, I have to rely on methods like AddB, GetB and RemoveB in order to enforce this rules.
public class Id { ... }
public class B{
private A _a;
internal B(A a){
_a = a;
}
private B() {
_a = default!;
}
}
public class A {
private List<B> _bs;
public IReadOnlyCollection<B> Bs => _bs.AsReadOnly();
public B AddB() {
// validate stuff
var b = new B(this);
_bs.Add(b);
return b;
}
public B GetB(Id id) {
//some linq to find B or throw if id not found
}
public B? FindB(Id id) {
return null if id not found
}
public void RemoveB(B b)
=> _bs.Remove(b);
}
Here the thing is that, as the business rules for managing B, A class is becoming more populated with methods like DoSomethingForB, most of them being linq queries or methods that perform calculations over the collection. And if I add another collection of class C then the complexity of A increases. So I would like to delegate linq queries and Get and Find methods to collection classes instead of relying on the generic List<T> method.
public class Id { ... }
public class B{
private A _a;
internal B(A a){
_a = a;
}
private B() {
_a = default!;
}
}
public class BCollection : IEnumerable<B> {
private List<B> _items;
public B GetB(Id id) {
//some linq to find B or throw if id not found
}
public B? FindB(Id id) {
return null if id not found
}
internal void Add(B b) => _items.Add(b);
// add some other methods like Remove etc.
}
public class A {
private BCollection _bs;
public BCollection Bs => _bs;
public A() {
_bs = new BCollection();
}
public B AddB() {
// validate stuff
var b = new B(this);
_bs.Add(b);
return b;
}
}
However, I am unsure whether this is a supported scenario on EF Core 3, specifically if EF Core 3 will know how to reconstruct my BCollection type, or if I have to follow some specific rules (perhaps implement an interface or do some special configuration in the DbContext configuration).
Thanks in advance.
I have a CXF generated class which has a collection as its only property. I need to map a single value from my DTO into an element of that collection, as in:
class DTO {
String dto;
}
class A {
String a;
}
class B {
List<A> b;
}
interface Mapper {
#Mappings({
#Mapping(source="dto", target="b.a")
})
B getBfromDTO(DTO dto);
}
Should this really work?
If so, how could I configure this mapping?
I couldn't find out a way to do this as a mapping, and from other answers from #Gunnar I now understand this is not possible, but I found a workaround using the annotation #AfterMapping.
#AfterMapping allow to specify methods to be run after a mapping occurs, so I created mappings for the non-collection properties of my objects and an #AfterMapping for filling collections in the objects.
class DTO {
String a;
String x;
}
class A {
String a;
}
class B {
String x;
List<A> b;
}
abstract class Mapper {
#Mappings({
#Mapping(source="x", target="x")
})
protected abstract B getBfromDTO(DTO dto);
#AfterMapping
protected void fillCollections(DTO dto, #MappingTarget B b) {
b.getB().add(dto.a);
}
}
If we have an entity A which contains a List of instances of entity B and entity B contains a List of instances of entity C, something like:
#Entity
class C { ... }
#Entity
class B {
#OneToMany
List<C> c;
}
#Entity
class A {
#OneToMany
List<B> b;
}
Is there a way to delete instances of C and update an instance of C from SimpleJPARepository based on entity A?