How to design many-to-many relationships in an object database? - oop

I thought it was about time to have a look at OO databases and decided to use db4o for my next little project - a small library.
Consider the following objects: Book, Category.
A Book can be in 0-n categories and a Category can be applied to 0-m Books.
My first thought is to have a joining object such as BookCatecory but after a bit of Googling I see that this is not appropriate for 'Real OO'.
So another approach (recommended by many) is to have a list in both objects: Book.categories and Category.books. One side handles the relationship: Book.addCategory adds Category to Book.categories and Book to Category.books. How to handle commits and rollbacks when 2 objects are been altered within one method call?
What are your thoughts? The second approach has obvious advantages but, for me at least, the first 'feels' right (better normed).

There are really only two ways I can think of to solve this problem, both of which you've mentioned. Personally, I would go with the first approach (creating a mapping object as an OO entity). This prevents you from keeping redundant information around and having to synchronize; it also means that if the association ends up having fields of its own (the date that the book was assigned to that category, let's say), they can be incorporated easily. We use this approach for a variety of associations in our system.
The OO entities would look like:
BookCategory {
Book book
Category category
}
Book {
Collection <BookCategory> categories
}
Category {
Collection <BookCategory> categories
}
Here you have to keep the relation object and the two collections in synch; however, the collections are optional in this case. Typically you could get the same information with an ORM query, something like:
select b.book from BookCategory b where b.category = MyCategory
The alternative is to have a setup like:
Book {
Collection<Category> categories
}
Category {
Collection<Books> books
}
If your ORM/DB tool automatically maintains the associations, this is fine; otherwise, you are stuck updating both collections. (In Hibernate, one side will have the property: inverse=true on the mapping; this side is not updated, so strictly speaking it doesn't need to be maintained. This seems to me like bad practice, though.)
If you typically only access the relation one way (for example, getting all of the books in a category), you could eliminate the collection on other side; then I think you would have to work around the ORM tool and use a native query in order to access the relationship from the other direction.
We use Hibernate (a java-based Object Relational Mapping tool) on our project; the Hibernate docs are a good reference for OO/relational design problems, though you may have to spend a little time learning Hibernate to make them useful:
http://docs.jboss.org/hibernate/stable/core/reference/en/html_single/#collections-ofvalues
HTH!

If you use object database you don't need to care how relations are stored in database. You define classes and relationships between them. Please read the reference guided to your database. Examples of relationships:
n:n attribute, referencing from the parent
------------------------------------------------------------------
class Person {
List addresses;
}
class Address {
}
n:n attribute, referencing from the child
------------------------------------------------------------------
class Person {
}
class Address {
List persons
}
n:n attribute, bidirectional references
------------------------------------------------------------------
class Person {
List addresses;
}
class Address {
List persons
}

I think you're just a little hung up on the relational db way of thinking. Lists in each object is the right OO thing to do. Commits and rollbacks are no problem, they happen in a transaction that commits everything or rolls back everything.

In a pure OO database such as GemStone the objects themselves have collections of references to other objects. When the object is referenced from the application the OODBMS generates a proxy that wraps the object. The schema for this is just the persisted object and its collection of references to the objects it refers to. The OODBMS does not necessarily need a link entity.
With an O/R mapping layer (assuming it is clever enough to do M:M relationships) the M:M relationship is manifested as a collection of subsidiary references on the object itself which the O/R mapper resolves to the link entity behind the scenes. Not all O/R mappers do this, so you may have a separate link object.

Do you have any particular reason you wanted to use an ODBMS? For simple data structures (such as categorizing books) you generally won't find any advantage in ODBMS over RDBMS, and in fact will have an easier time working in the much-more-standardized world of RDBMS. ODBMS has very tangible advantages when you are working with complex data types or literal persistence/storage of dynamic objects. ODBMS also is cited as being much faster and more scalable than RDBMS, though I can offer little insight into this myself. Here are a couple pages that discuss RDBMS vs. ODBMS, however:
Whatever Happened to Object-Oriented Databases
Object-Oriented Database vs. Object-Rleational Database (SO)

I would avoid data duplication because then you run into all kinds of problems with merging the differences.
the trick to this is references.
the result is that I would have each object contain a collection of references to the other object type as well as having an independent collection of the other objects.
The matching table is a relational concept, unless that intermediary connecting class may have properties that are not attributable to either of the objects. It is there as it enables queries to be written in a powerful manner as it reduces the relation to 2 one to many relations and greatly reduces data duplication. If you did this in a relation database without the matching table then things would get evil very quickly - how would an update operate? Personally i find the attraction of oo databases to be stepping away from this
the way that i would tie all the objects together is via events in code to some kind of transaction handler to allow the caching of objects states. so rather than objects manipulating each others properties they request a change through the handler and await the result in a callback.

Related

Unidirectional parent-child association not null

I have a class structure which is akin to a PurchaseOrder (parent) and PurchaseOrderLine (child) pattern, where the order lines will only be saved to the DB by saving the parent PurchaseOrder and will only ever be accessed via the parent too.
The DB has PurchaseOrderLine.PurchaseOrder set to not permit null values.
It seems from searching through the web that it is not possible to have a uni-directional association from PurchaseOrder via an IList property without having to have a property on the line pointing back when the child has a NOT NULL constraint for its PurchaseOrder column.
Is this really the case? It seems like one of the most basic things one would want to do with an ORM, I find it difficult to accept that a product as mature as NHibernate cannot handle such a basic scenario.
No it's not the case. Please see the example provided in the answer to this question: When to use inverse=false on NHibernate / Hibernate OneToMany relationships?
Well, it may be the case that you can't have unidirectional one-to-many relationship defined only on one side, but I'll argue with your statement that this is "one of the most basic things one would want to do with an ORM".
One of the most basic things would be to have unidirectional one-to-many defined only on many side - as it is natural for RDBM tables. And ORMs (despite the common misconception) are not intended (or able) to fully abstract domain model from underlying data source. Even if in some cases they can, the database side suffers from select N+1 problems or very ineffective queries.
Defining one-to-many at one side makes an impression that i.e. counting the collection is cheap. It is the case with plain object graphs, but not with NHibernate entities, as reading collection causes (at least one) call to the database. Eager fetching from one side is also not able to properly use database join mechanism in the way it's intended to be used (opposite to eager fetch from many side).
Even if I don't agree with a lot of arguments, I think it is useful to read some of the articles saying that "ORM is an anti-pattern", like this one. They helped me to leverage the way I think about ORMs and make me think about ORMs as a compromise between two not matching paradigms, but not the way to hide one behind another.
This can now be achieved in NH3 using the Not.KeyNullable()
this.HasMany(x => x.Actions)
.Access.BackingField()
.KeyColumn("[Application]")
.Not.KeyNullable()
.Cascade.AllDeleteOrphan();

How does one architect an entity in Core Data with a generic relationship?

Say you need to architect an app with an entity that can be associated with multiple other kinds of entities. For example, you have a Picture entity that can be associated with a Meal entity, a Person entity, a Boardroom entity, a Furniture entity, etc. I can think of a number of different ways to address this problem, but -- perhaps because I'm new to Core Data -- I'm not comfortable with any of them.
The most obvious approach that comes to mind is simply creating a relationship between Picture and each entity that supports associated pictures, but this seems sloppy since pictures will have multiple "null pointers."
Another possibility is creating a superentity -- Pictureable -- or something. Every entity that supports associated pictures would be a subentity of Pictureable, and Picture itself would have a one-to-one with Pictureable. I find this approach troubling because it can't be used more than once in the context of a project (since Core Data doesn't support multiple inheritance) AND the way Core Data seems to create one table for any given root entity -- assuming a SQLite backing -- has me afeard of grouping a whole bunch of disparate subentities under the umbrella of a common superentity (I realize that thinking along these lines may smack of premature optimization, so let me know if I'm being a ninny).
A third approach is to create a composite key for Picture that consists of a "type" and a "UID." Assuming every entity in my data model has a UID, I can use this key to derive an associated managed object from a Picture instance and vice versa. This approach worries me because it sounds like it might get slow when fetching en masse; it also doesn't feel native enough to me.
A fourth approach -- the one I'm leaning towards for the app I'm working on -- is creating subentities for both Picture and X (where X is either Meal, Person, Boardroom, etc.) and creating a one-to-one between both of those subentities. While this approach seems like the lesser of all evils, it still seems abstruse to my untrained eye, so I wonder if there's a better way.
Edit 1: In the last paragraph, I meant to say I'm leaning towards creating subentities just for Picture, not both Picture and X.
I think the best variations on this theme are (not necessarily in order):
Use separate entities for the pictures associated with Meal, Person, Boardroom, etc. Those entities might all have the same attributes, and they might in fact all be implemented using the same class. There's nothing wrong with that, and it makes it simple to have a bidirectional relationship between each kind of entity and the entity that stores its picture.
Make the picture an attribute of each of the entity types rather than a separate entity. This isn't a great plan with respect to efficiency if you're storing the actual picture data in the database, but it'd be fine if you store the image as a separate file and store the path to that file in an attribute. If the images or the number of records is small, it may not really be a problem even if you do store the image data in the database.
Use a single entity for all the pictures but omit the inverse relationship back to the associated entity. There's a helpful SO question that considers this, and the accepted answer links to the even more helpful Unidirectional Relationships section of the docs. This can be a nice solution to your problem if you don't need the picture->owner relationship, but you should understand the possible risk before you go down that road.
Give your picture entity separate relationships for each possible kind of owner, as you described in the first option you listed. If you'll need to be able to access all the pictures as a group and you need a relationship from the picture back to its owner, and if the number of possible owner entities is relatively small, this might be your best option even if it seems sloppy to have empty attributes.
As you noticed, when you use inheritance with your entities, all the sub-entities end up together in one big table. So, your fourth option (using sub-entities for each kind of picture) is similar under the hood to your first option.
Thinking more about this question, I'm inclined toward using entity inheritance to create subentities for the pictures associated with each type of owner entity. The Picture entity would store just the data that's associated with any picture. Each subentity, like MealPicture and PersonPicture, would add a relationship to it's own particular sort of owner. This way, you get bidirectional Meal<->MealPicture and Person<->PersonPicture relationships, and because each subentity inherits all the common Picture stuff you avoid the DRY violation that was bugging you. In short, you get most of the best parts of options 1 and 3 above. Under the hood, Core Data manages the pictures as in option 4 above, but in use each of the picture subentities only exposes a single relationship.
Just to expand a bit on Caleb's excellent summation...
I think it's important not to over emphasize the similarities between entities and classes. Both are abstractions that help define concrete objects but entities are very "lightweight" compared to classes. For one thing, entities don't have behaviors but just properties. For another, they exist purely to provide other concrete objects e.g. managed object context and persistent stores, a description of the data model so those concrete objects can piece everything together.
In fact, under the hood, there is no NSEntity class, there is only an NSEnitity***Description*** class. Entities are really just descriptions of how the objects in an object graph will fit together. As such, you really don't get all the overhead an inefficiency of multiplying classes when you multiply entities e.g. having a bunch of largely duplicate entities doesn't slow down the app, use more memory, interfere with method chains etc.
So, don't be afraid to use multiple seemingly redundant entities when that is the simplest solution. In Core Data, that is often the most elegant solution.
I am struggling with esactly this dilemma right now. I have many different entities in my model that can be "quantified". Say I have Apple, Pear, Farmer for all of those Entities, I need a AppleStack, PearStack, FarmerGroup, which are all just object+number. I need a generic approach to this because I want to support it in a model editor I am writing, so I decided I will define a ObjectValue abstract entity with attributes object, value. Then I will create child entities of ObjectValue and will subclass them and declare a valueEntity constant. this way I define it only once and I can write generic code that, for example, returns the possible values of the object relationship. Moreover if I need special attributes (and I actually do for a few of those) I can still add them in the child entities.

Basic question about OOP

I often have the same trouble when I have to design my class for a web application. The requirements are :
- maintainable (no copy-paste for instance)
- layers fully separated (the business layer doesn't have to know which method of the data layer is used)
- high performance : don't load useless data.
First I have a table with all my customers and their addresses :
Code :
Customer
--Id
--Name
--Address
----City
----ZC
----Street
Now I want a table (in another page) with all my customers and the books that they bought, I have a few possibilities :
1/ I create a new class :
Code :
CustomerWithBooks
--Id
--Name
--Books[]
----ID
----name
PRO : I load only the useful data
CONS : I build my class after my UI , and there is copy-paste.
2/ I add Books[] to the first class.
PRO : Everything is in the same class, it's maintainable
CONS : I load the address for nothing. If I don't load the address I can : lazy loading, but I really don't like it, or when I use my class I have to know which method of my DAL i called, and I don't like it.
3/ I use inheritance :
Code :
ClientBase
--ID
--Name
ClientWithBooks : ClientBase
--Books[]
ClientWithAdress : ClientBase
--Address
PRO: really maintenable, and I don't load data for nothing
CONS : What do I do if in one UI I want to show the Books AND the Address ?
4/ ?? I hope there is a perfect solution
You option 1 is close to good, assuming I understand it correctly. A customer and a book are two completely different things. You want that data/functionality separate, and should not inherit from any common base class (that you have made).
As the "Con" you say: I build my class after my UI , and there is copy-paste.
A. If you mock up some UI to help clarify requirements before you settle on your design and code up classes, that's good, not bad.
B. Good arrangement of your domain objects helps eliminate copy/paste, not cause it. If you have some seemingly repetitive code within your well-arranged classes (often data access code) that's typical, don't worry. You can address with with a good data-access layer/tool, good shared logging resources, etc. Repetitive code within your classes just means you have more design improvement to do, not that having separate classes for all your domain realities is bad.
On the page where you need to deal with both customers and books, you will use customer objects and book objects, and probably a books collection object. And depending on how your db/object-model are set up, you might be dealing with other objects to get form customer to the books they bought. For example, the customers probably buy 1 or more books at the same time, and these are tied to an Order object, which has a reference to a customer. So, you'll probably go from a
Customer to an
Orders collection containing all of that customers orders to the individual
Order objects and from there to a corresponding
Books collection containing all the
Book objects that relate to that Order object.
None of these need to inherit from each other. Now, let's say getting all the books bought by a customer is something you do a lot, and you want to streamline that. You then want to have a Books collection directly off of Customer that gives you that, though the sql queries you use to get those books still goes through Orders in the db. You must start with your object model (and tables behind the scenes) reflecting reality accurately. Even if this give you seemingly many classes, it is more simple in the end. You might end up with some inheritance, you might not.
I would to avoid 2 and 3, because it locks you into a restrictive hierarchy that doesn't really meet your needs. As you point out, there could be any combination of things that you want, such as customers and their books, and maybe their address, and maybe their ordering history. Or maybe you'll want a book with it's list of customers. Since your underlying business information is not really hierarchical, you should try to avoid making your object model unnecessarily hierarchical. Otherwise, you will build in restrictions that will cause you a lot of headaches later, because you can't think of all the scenerios now.
I think you're on the right track with 1. I would say to create some basic classes for Customers and Books, and then create a CustomerBook association class that contains an instance both the customer and the book. Then you can have you methods worry about how to load the data into that list for a given scenerio.
I would stick the address into Customer, and have a separate collection of books.
Bookshelf
--Books[]
This way, a Customer doesn't have, but can have, one or more books associated to him. PHP-code example following:
class BookshelfFactory {
public static function getBookshelf(Customer $customer) {
// perform some fetching here
return $bookshelf;
}
}
You're sort of designing backwards from an OOA&D standpoint. It's normal to use data-driven design at the persistence (usually a relational database) layer. But in OOA&D it's more normal to think of the messages an object will send and receive (you model an object's methods not its members). I would think about it this way:
Customer
+getBooks():List<Book>
+getAddress():Address
I think your problem is an issue for the implementation of your data mapping layer.
You can have highly performant queries with JOINS that return you the Customers as well as their Books.
Your mapping layer maps this into the appropriate unique objects and is responsible for creating the right 1-many aggregation for your objects.
In addition you could cater for shallow loading, for display properties to save unnecessary amounts of data to be transferred where you only need a few attributes per object.

Where should I store virtual/calculated/complex object fields in my models?

I have models corresponding to database tables. For example, the House class has "color", "price", "square_feet", "real_estate_agent_id" columns.
It is very common for me to want to display the agent name when I display information about a house. As a result, my House class has the following fields:
class House {
String color;
Double price;
Integer squareFeet;
Integer realEstateAgentId;
String realEstateAgentName;
}
I've been referring to realEstateAgentName as a virtual field, as it is pulled from a foreign table (join on real_estate_agent_id).
This doesn't feel right to me, as it mixes actual database columns with foreign object's properties. But it's quick, and in many cases it really works out well.
Other times I find myself doing something like this:
class House {
String color;
Double price;
Integer squareFeet;
Integer realEstateAgentId;
RealEstateAgent realEstateAgent;
}
As you can see, I'm storing the actual object corresponding to the ID that is stored in the House table.
I tend to make the decision to store the entire object vs some key information associated with the ID (e.g. Name) depending on the likelihood I see of needing to access other information about the object it represents.
I have a few questions:
Of the two methods I've been mixing and matching, which is best? I'm leaning towards storing the id + the object, rather than pulling out just the properties from the foreign object that I think I may need. Of the two, this seems more "correct." But it's not perfect, because in many cases I don't have any need to hydrate the entire foreign object, and doing so would cause undue waste of resources or would not be feasible because of the amount of data or the number of joins that would be required when I don't have any use for all the info being brought in. Given that this is the case, it seems like a poor design choice because I will have lots of null fields that aren't really null in my database, but are so in memory simply because there was no need to populate them -- now I have to keep track of which ones I populated.
But is it best practice to store an ID alongside the object it represents? Should I even be storing the object as a property, or should it live externally in some map, with the ID being the key?
In an Object world it seems like the ID shouldn't even be stored as a property, with the foreign Object it represents being the logical replacement. But with everything being tightly coupled with a relational database it doesn't seem very feasible.
Is this frustrating impurity of my models/classes something I just have to live with, or are there patterns out there that address this by having some kind of fork or parent/child subclassing going on where one is a "pure" object while the other is flat like the database?
EDIT: I am looking for design suggestions here rather than specific ORM frameworks like Hibernate/nHibernate/etc. The particular language I'm working in does not have an ORM solution for my language version that I am satisfied with, and the examples were Java-esque but that's not what my source code is written in.
I can tell about Hibernate, because this is the ORM tool I am most familiar with. I believe that other ORM tools also support similar behaviour to some extent.
Hibernate solves your problem with lazy loading. You add your agent as a property to the house, and by default, when the house object is loaded, the agent is represented by a proxy object generated by Hibernate, which contains only the ID. If you query some other property of the agent, Hibernate loads the full object in the background:
class House {
String color;
Double price;
Integer squareFeet;
RealEstateAgent realEstateAgent;
// getters, setters,...
}
House house = (House) session.load(House.class, new Long(123));
// at this point, house refers to a proxy object created by Hibernate
// in the background - no house or agent data has been loaded from DB
house.getId();
// house still refers to the proxy object
RealEstateAgent agent = house.getRealEstateAgent();
// house is now loaded, but agent not - it refers to a proxy object
String name = agent.getName(); // Now the agent data is loaded from DB
OTOH if you are sure that for a specific class you (almost) always need a specific property, you can specify eager loading in the ORM mapping for that property, in which case the property is loaded as soon as the containing object. In the mapping you can also specify whether you want a join query or a subselect query.
LINQ to SQL uses ID + Object and it works out well. I prefer that model as it's most flexible. Hibernate can do the same. One issue you will face is deep loading: when do you actually load the object and not just the ID? Both LINQ to SQL and Hibernate have lazy loading and give you control over this issue.
The Entity Framework however looks to give you this complete control where you can decide just how the data appears regardless the physical underpinnings. It has not been fully realized yet however.
There's really no impurity going on here. The problem is you're trying to represent an abstraction of data that is relationship in an object oriented fashion. To get around the pains of developing like this, larger scale projects are moving to Domain Driven Design where the underlying data is abstracted out into logical groupings of Repositories. Thinking in tables as classes can be problematic for large scale solutions.
Just my 2 cents.
Hibernate, the most popular ORM tool in the Java ecosystem, usually allows you to do this:
class House {
String color;
Double price;
Integer squareFeet;
RealEstateAgent realEstateAgent;
}
This translates to a DB-table that looks like this: house(id, color, price, squareFeet, real_estate_agent_id)
If you need to print the name of the agent you just walk traverse the object graph:
house.getRealEstatAgent().getName()
Through lazy loading, this is done quite efficiently. I wouldn't worry about the fact that an extra query trip to the database may have to be done until your stress tests prove this to be a problem.
Edit after your edit:
All the solutions out there have dealt with the paradigm mismatch (between the OO and Relational worlds) in a similar fashion. The designs have been made, the problem is solved. And yes, it remains a pain in the butt to deal with as an application developer but I suppose it is just the way it is as long as we want to use relational databases and object oriented persistence together.

How to solve cross referencess in OOP?

I encountered this a couple of times now, and i wondered what is the OO way to solve circular references. By that i mean class A has class B as a member, and B in turn has class A as a member.
One example of this would be class Person that has Person spouse as a member.
Person jack = new Person("Jack");
Person jill = new Person("Jill");
jack.setSpouse(jill);
jill.setSpouse(jack);
Another example would be Product classes that have some Collection of other Products as a member. That collection could for example be products that people who are interested in this product might also be interested in, and we want to upkeep that list on a per-product base, not on same shared attributes (e.g. we don't want to just display all other products in the same category).
Product pc = new Product("pc");
Product monitor = new Product("monitor");
Product tv = new Product("tv");
pc.setSeeAlso({monitor, tv});
monitor.setSeeAlso({pc});
tv.setSeeAlso(null);
(these products are just for making a point, the issue is not about wether or not certain products would relate to each other)
Would this be bad design in OOP in general? Would/should all OOP languages allow this, or is it just bad practice? If it's bad practice, what would be the nicest way of solving this?
The examples you give are (to me, anyway) examples of reasonable OO design.
The cross-referencing issue you describe isn't an artifact of any design process but a real-life characteristic of the things you're representing as objects, so I don't see there's a problem.
What have you encountered that has given you the impression that this approach is bad-design?
Update 11 March:
In systems that lack garbage collection, where memory management is explicitly managed, one common approach is to require all objects to have an owner - some other object responsible for managing the lifetime of that object.
One example is Delphi's TComponent class, which provides cascading support - destroy the parent component, and all owned components are also destroyed.
If you're working on such a system, the kinds of referential loop described in this question may be considered poor design because there's no clear owner, no one object responsible for managing lifetimes.
The way that I've seen this handled in some systems is to retain the references (because they properly capture the business concerns), and to add in an explicit TransactionContext object that owns everything loaded into the business domain from the database. This context object takes care of knowing which objects need to be saved, and cleans everything up when processing is complete.
It's not a fundamental problem in OO design. An example of a time it might become a problem is in graph traversal, for instance, finding the shortest path between two objects - you could potentially get into an infinite loop. However, that's something you would have to consider on a case-by-case basis. If you know there could be cross-references in a case like that, then code some checks in to avoid infinite loops (for instance, maintaining a set of visited nodes to avoid re-visiting). But if there's no reason it could be a problem (such as in the examples you gave in your question), then it's not bad at all to have such cross-references. And in many cases, as you've described, it's a good solution to the problem at hand.
I do not think this is an example of cross referencing.
Cross referencing usually pertains to this case:
class A
{
public void MethodA(B objectB)
{
objectB.SomeMethodInB();
}
}
class B
{
public void MethodB(A objectA)
{
objectA.SomeMethodInA();
}
}
In this case each object kind of "reaches in" to each other; A calls B, B calls A, and they become tightly coupled. This is made even worse if A and B are in different packages/namespaces/assemblies; in many cases those would create compile time errors as assemblies are compiled linearly.
The way to solve that is to have either object implement an interface with the desired method.
In your case you only have one level of "reaching in":
public Class Person
{
public void setSpouse(Person person)
{ ... }
}
I do not think this is unreasonable, nor even a case of cross-referencing/circular references.
The main time this is a problem is if it becomes too confusing to cope with, or maintain, as it can become a form of spaghetti code.
However, to touch on your examples;
See Also is perfectly valid if this is a feature you need in your code - it is a simple list of pointers (or references) to other items a user may be interested in.
Similarily it is perfectly valid to add spouse, as this is a simple real world relationship that would not be confusing to someone maintaining your code.
I have always seen it as a potential code smell, or perhaps a warning to take a step back and rationalise what I am doing.
As for some systems finding recursive relationships in your code (mentioned in a comment above), these can come up regardless of this sort of design. I have recently worked on a metadata capture system that had recursive 'types' of relationships - i.e Columns being logically related to other columns. It needs to be handled by the code trying to parse your system.
I don't think the circular references as such are a problem.
However, putting all those relationships inside objects may add too much clutter, so you may instead want to represent them externally. E.g. you might use a hash table to store relationships between products.
Referencing other objects is not a real bad OO design at all. It's the way state is managed within each object.
A good rule of thumb is the Law of Demeter. Look at this perfect paper of LoD (Paperboy and the wallet): click here
One way to fix this is to refer to other object via an id.
e.g.
Person jack = new Person(new PersonId("Jack"));
Person jill = new Person(new PersonId("Jill"));
jack.setSpouse(jill.getId());
jill.setSpouse(jack.getId());
I'm not saying it is a perfect solution, but it will prevent circular references. You are using an object instead of a object reference to model the relationship.