How to solve circular reference?
In most cases when I've had to have two things reference each other, I've created an interface to remove the circular reference. For example:
BEFORE
public class Foo
{
Bar myBar;
}
public class Bar
{
Foo myFoo;
}
Dependency graph:
Foo Bar
^ ^
| |
Bar Foo
Foo depends on Bar, but Bar also depends on Foo. If they are in separate assemblies, you will have problems building, particularly if you do a clean rebuild.
AFTER
public interface IBar
{
}
public class Foo
{
IBar myBar;
}
public class Bar : IBar
{
Foo myFoo;
}
Dependency graph:
Foo, IBar IBar
^ ^
| |
Bar Foo
Both Foo and Bar depend on IBar. There is no circular dependency, and if IBar is placed in its own assembly, Foo and Bar being in separate assemblies will no longer be an issue.
How to resolve circular struct dependencies in C
The way to do this is to pre-define the structs using empty definition
typedef struct _A A;
typedef struct _B B;
typedef struct _A {
B *b;
} A;
typedef struct _B {
A a;
} B;
You can put the pre-definitions in a global include file to include from wherever you need.
`
How to solve circular reference in JPA associations?
Circular dependencies aren't a problem in themselves with JPA.
There are two potential problems with them:
From a software design perspective circular dependencies create a cluster of classes that you can't easily break up.
You can easily get rid of them in your case by making the relationship a unidirectional one and replace the other direction by a query, if you really have to.
Is it worth it in your case?
It depends how closely your two entities are really related.
I'd try to avoid bidirectional relationships, because it is easy to make mistakes, like not keeping both sides of the relationship in sync.
But in most cases I wouldn't sweat it.
Most software as way more serious design issues.
The other problem occurs when something tries to navigate this loop until its end, which obviously doesn't work. The typical scenarios are:
- rendering it into JSON (or XML). This is what
@JsonIgnore
& Co takes care of by not including properties in the JSON. equals
,hashCode
,toString
are often implemented to call the respective methods of all referenced objects.
Just as the JSON rendering this will lead to stack overflows.
So make sure to break the cycle in these methods as well.
JPA itself doesn't have a problem with cycles because it will look up entities in the first level cache.
Assuming you load an Authority
and everything is eagerly loaded, JPA will put it in the first level cache, before checking the referenced user id. If it is present in the cache it will use that instance.
If not it will load it from the database, put it in the cache and then check for the authorities ids in the cache. It will use the ones found and load the rest.
For those it will again check the user id, but those are the user we just loaded, so it is certainly in the cache.
Therefore JPA is done and won't get lost in a cycle.
It will just skip the annotated
R solving circular reference
Perhaps something like this?
dat <- data.frame(
indicator = rep(c(1,0,0), times = 4),
interest = c(0,54,33,678,987,544,321,345,678,907,567,0)
)
intersolve <- function(indicator, interest){
indicators = rev(cumsum(rev(indicator) == 1))
sums = rev(tapply(interest, indicators, sum))
interest_payment = rep(sums[-1], each = 3) * indicator
return(interest_payment)
}
dat$interest_payment = intersolve(indicator = dat$indicator, interest = dat$interest)
dat
# indicator interest interest_payment
# 1 1 0 765
# 2 0 54 0
# 3 0 33 0
# 4 1 678 1852
# 5 0 987 0
# 6 0 544 0
# 7 1 321 1930
# 8 0 345 0
# 9 0 678 0
# 10 1 907 567
# 11 0 567 0
# 12 0 0 0
Edit
The following function automatically detects the pattern of 1's.
intersolve2 <- function(indicator, interest){
n = length(interest)
indicators = rev(cumsum(rev(indicator) == 1))
sums = rev(tapply(interest, indicators, sum))
lens = rev(table(indicators))[-1]
lens[length(lens)] = lens[length(lens)] + 1
interest_payment = rep(sums[-1], times = lens) * indicator
if (indicator[n] == 1){interest_payment[n]=interest[n]}
return(interest_payment)
}
Value-equals and circular references: how to resolve infinite recursion?
For the general case that I am interested in
-- where we have classes C1
, ..., Cn
where each of these classes can have any number of VALUES (like int
, string
, ...) as well as any number of REFERENCES to any other classes of C1
, ..., Cn
(e.g. by having for each type Ci
a field ICollection<Ci>
) --
the question "Are two objects A
and B
equal?", in the sense of equality that I described here,
seems to be EQUIVALENT to
the question "For two finite, directed, connected, colored graphs G
and H
, does there exist an isomorphism from G
to H
?".
Here is the equivalence:
- graph vertices correspond to
object
s (class instances) - graph edges correspond to references to
object
s - color corresponds to the conglomerate of values and the type itself (i.e. colors of two vertices are the same if their corresponding
object
s have the same type and the same values)
That's an NP-hard question, so I think I'm going to discard my plan to implement this and go with a circular-reference-free approach instead.
How to Resolve Circular Reference in Header File
You can move the definition of thiswontcompile
to the end of the header file, you just need to make the function inline
.
#include <vector>
class Box;
class Item {
int row;
int column;
Box *box;
public:
Item(Box *b) : box(b) {}
void thiswontcompile();
void foo();
};
class Box {
std::vector<Item*> items;
public:
Box() {}
void addsquare(Item *sq) { items.push_back(sq); }
void bar() { for (int i=0; i<items.size(); i++) items[i]->foo(); }
void dosomething();
};
inline void Item::thiswontcompile() { box->dosomething(); }
Solving circular reference
@Transient
private B messageOwner;
This does for the JSON serialization what the transient
type modifier does for the normal serialization. If the JSON library supports it.
Of course the messageOwner
will be null after deserialisation.
How to solve circular reference when serializing an object which have a class member with the same type of that object
I think using ExclusionStrategy
is not the right approach to solve this problem.
I would rather suggest to use JsonSerializer
and JsonDeserializer
customized for your StructId
class.
(May be an approach using TypeAdapter
would be even better,
but I didn't have enough Gson experience do get this working.)
So you would create your Gson
instance by:
Gson gson = new GsonBuilder()
.registerTypeAdapter(StructId.class, new StructIdSerializer())
.registerTypeAdapter(StructId.class, new StructIdDeserializer())
.setPrettyPrinting()
.create();
The StructIdSerializer
class below is responsible for converting a StructId
to JSON.
It converts its properties Name
, Type
and ChildId
to JSON.
Note that it does not convert the property ParentId
to JSON,
because doing that would produce infinite recursion.
public class StructIdSerializer implements JsonSerializer<StructId> {
@Override
public JsonElement serialize(StructId src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("Name", src.Name);
jsonObject.add("Type", context.serialize(src.Type));
jsonObject.add("ChildId", context.serialize(src.ChildId)); // recursion!
return jsonObject;
}
}
The StructIdDeserializer
class below is responsible for converting JSON to a StructId
.
It converts the JSON properties Name
, Type
and ChildId
to corresponding Java fields in StructId
.
Note that the ParentId
Java field is reconstructed from the JSON nesting structure,
because it is not directly contained as a JSON property.
public class StructIdDeserializer implements JsonDeserializer<StructId> {
@Override
public StructId deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
StructId id = new StructId();
id.Name = json.getAsJsonObject().get("Name").getAsString();
id.Type = context.deserialize(json.getAsJsonObject().get("Type"), StructType.class);
JsonElement childJson = json.getAsJsonObject().get("ChildId");
if (childJson != null) {
id.ChildId = context.deserialize(childJson, StructId.class); // recursion!
id.ChildId.ParentId = id;
}
return id;
}
}
I tested the code above with this JSON input example
{
"Name": "John",
"Type": "A",
"ChildId": {
"Name": "Jane",
"Type": "B",
"ChildId": {
"Name": "Joe",
"Type": "A"
}
}
}
by deserializing it withStructId root = gson.fromJson(new FileReader("example.json"), StructId.class);
,
then by serializing that withSystem.out.println(gson.toJson(root));
and got the original JSON again.
Excel Circular Reference error without circular reference
I'm not sure if I should delete this question, or if this is a valid answer. I guess I would like to have heard of this as a possible solution.
So I copied the formula in the question as text; deleted it (which removed the error if I close and open the sheet), I then pasted the same formula back into the sheet, close the sheet, re-open the sheet, and now, no more circular reference error. I wish I could say I understand why this would work - I was just desperately trying anything and it seemed the only option left.
Related Topics
Why Are Some Members Missing When Trying to Print an Object by Serializing to JSON
Accelerating Bitmap Grayscale Conversion, Is Openmp an Option in C#
Why Is Addrange Faster Than Using a Foreach Loop
Spinwait VS Sleep Waiting. Which One to Use
How to Fill Forms and Submit with Webclient in C#
Can a Dbcontext Enforce a Filter Policy
How to Execute a Java Program from C#
Validating for Large Files Upon Upload
How to Debug a Single Thread in Visual Studio
How to Async Download Multiple Files Using Webclient, But One at a Time
Entity-Framework Code Is Slow When Using Include() Many Times
How to Add Event Handler for Dynamically Created Controls at Runtime