掲示板

ServiceBuilder, Entity referencing collections of Entity

thumbnail
16年前 に Ray Augé によって更新されました。

ServiceBuilder, Entity referencing collections of Entity

Liferay Legend 投稿: 1197 参加年月日: 05/02/08 最新の投稿
Hey All,

I was experimenting tonight and I realized that we can't have an entity
referencing a collection the same type as the entity.

e.g.

<entity name="Person">
  ...
  <column name="siblings" type="Collection" entity="Person" mapping-table="Persons_Persons" />
  ...
</entity>


This seems like it would be a fairly common type of relationship and
frankly I'm surprised that we don't already support it... though it
seems to only result in problems in one generated file:

PersonPersistenceImpl


Seems that the inner classes break due to the fact that the referenced
entity have the same pKey name as the referrer. Wondering if perhaps we
could solve this by doing something like if the pKey names are the same
append an underscore to the reference, something like this


protected class AddPerson extends SqlUpdate {
	protected AddPerson(PersonPersistenceImpl persistenceImpl) {
		super(persistenceImpl.getDataSource(),
			"INSERT INTO Persons_Persons (personId, personId_) VALUES (?, ?)");

		_persistenceImpl = persistenceImpl;

		declareParameter(new SqlParameter(Types.BIGINT));
		declareParameter(new SqlParameter(Types.BIGINT));

		compile();
	}

	protected void add(long personId, long personId_) {
		if (!_persistenceImpl.containsPerson.contains(personId, personId_)) {
			update(new Object[] { new Long(personId), new Long(personId_) });
		}
	}

	private PersonPersistenceImpl _persistenceImpl;
}



It would be nice to be able to handle these kinds of self references.


Raymond Augé
Software Engineer
Liferay, Inc.
Enterprise. Open Source. For Life.
thumbnail
16年前 に Jorge Ferrer によって更新されました。

RE: ServiceBuilder, Entity referencing collections of Entity

Liferay Legend 投稿: 2871 参加年月日: 06/08/31 最新の投稿
Hi Ray,

Fully agreed, we should support that type of references. What I would suggest though is that instead of just adding an underscore I would add a postfix with the number of the relationship. For example:

personId_siblings


That solves the issue of having several relationships to the same table and it would make the code easier to read.
thumbnail
16年前 に Ray Augé によって更新されました。

Re: [Liferay Forums][Liferay Core Developers]RE: ServiceBuilder, Entity ref

Liferay Legend 投稿: 1197 参加年月日: 05/02/08 最新の投稿
> What I would suggest though is that instead of just adding an
> underscore I would add a postfix with the number of the relationship.
> For example:
>
>
personId_siblings

>
> That solves the issue of having several relationships to the same
> table and it would make the code easier to read.


I like it!
thumbnail
16年前 に Joel Kozikowski によって更新されました。

RE: ServiceBuilder, Entity referencing collections of Entity

Expert 投稿: 405 参加年月日: 06/06/28 最新の投稿
Ray Augé:
protected class AddPerson extends SqlUpdate {
	protected AddPerson(PersonPersistenceImpl persistenceImpl) {
		super(persistenceImpl.getDataSource(),
			[b]"INSERT INTO Persons_Persons (personId, personId_) VALUES (?, ?)"[/b]);



I've done a lot of work in the ORM area (outside of Liferay). I've even written my own "poor man's persistence" layer that generates ORM code not using Hibernate (when lightweight solutions are needed).

Collections of entities (self referenced, or otherwise) depends on if you are talking about a "one to many" or "many to many" relationship. So, if you are going to refactor ServiceBuilder to support this, you need to be able to specify this "multiplicity" of the relationship.

The "Persons_Persons" join table you describe above is only necessary for a "many to many" relationship, which is actually not nearly as common as the "one to many."

If I have:

EntityA 0..1 ---> 0..* EntityB

(that is, EntityA contains zero or more of EntityB, and EntityB references only zero or 1 of EntityA), then the proper way to "generate" this code is to put a single "foreign key" field in EntityB that is the primary key of EntityA. You then generate a query something like:

SELECT * FROM EntityB WHERE EntityB.entityA_FK = ?


and you pass in the Id of Entity A. No need for that middle "join" table.

The case of self-referential items is just a special case of the above. If you have Person object, and you wanted a field like "Person biologicalFather", you'd only need to put have a single FIELD that is "biologicalFatherId" in the Person table, and not some third join table.

Of course, in your example, you DO have a "many to many" because any one person can have more than one sibling, and each sibling can also have many. My only point is that the "multiplicity" is an important factor.

The Hibernate guys would argue that you really never have a "many to many" table, because there is usually SOME type of additional information in that "middle" join table beyond the two foreign key references. That is a different debate...

My only point is that if we could express those relationships correctly, you could return a Collection<Entity> using just SQL queries (or, Hibernate queries). I believe by not being able to "express" associations and having the code generate appropriately, we are losing a powerful and significant part of Hibernate's functionality. IIRC, ServiceBuilder DOES have the syntax to express foreign key relationships, but it was disable due to performance issues (but that an altnerate technique surfaced that SHOULD have re-enabled it). I'll see if I can find the post.
thumbnail
15年前 に jenny heinrich によって更新されました。

RE: ServiceBuilder, Entity referencing collections of Entity

Junior Member 投稿: 47 参加年月日: 08/03/14 最新の投稿
Hello,

I use the ServiceBuilder and it works fine. But I have a question on how to use it
with collections.

My class Page has a one-to-many relationship.
The collection is defined in the service.xml in the entity tag:

<column name="assets" type="Collection" entity="Asset" mapping-key="pId" />

If I load a list of Pages I expected that each page has a method getAssets()
to access the asset list. I add the get / set method to my PageImpl class but
I don´t want to iterate over each element of the list to
load the assets manually for each list entry.

Is there any "best practice" way how to do this using the Service Builder?
Perhaps changing the findAll() method in the ...PersistenceImpl?

Using hibernate I it could be the following:
<set name="assets" inverse="true">
<key column="pId">
<one-to-many class="org.test.Asset"/>
</set>

If I change the hibernate mapping in the ext-hbm.xml it is overwritten by starting the ServiceBuilder.
Is there any possibility to avoid this?

Thanks in advance,

Jenny
12年前 に Hiran Chaudhuri によって更新されました。

RE: ServiceBuilder, Entity referencing collections of Entity

Regular Member 投稿: 188 参加年月日: 10/09/01 最新の投稿
jenny heinrich:
If I load a list of Pages I expected that each page has a method getAssets()
to access the asset list. I add the get / set method to my PageImpl class but
I don´t want to iterate over each element of the list to
load the assets manually for each list entry.

Is there any "best practice" way how to do this using the Service Builder?
Perhaps changing the findAll() method in the ...PersistenceImpl?

I do not know whether you solved your problem meanwhile.

But basically what you are searching for is eager loading of those references. It can be configured in Hibernate and other ORM tools.
Who knows how to set this up in ServiceBuilder?
thumbnail
12年前 に Ray Augé によって更新されました。

RE: ServiceBuilder, Entity referencing collections of Entity

Liferay Legend 投稿: 1197 参加年月日: 05/02/08 最新の投稿
Why does it have to be eager loading? This is not a smart pattern and should really be avoided.

It's very simple to edit the EntityImpl class that is generated and add methods which return related entites, this way you can also provide for limits (pagination as well).

Check UserImpl class to see examples of methods on users that return relations.
9年前 に Ivan Valchev によって更新されました。

RE: ServiceBuilder, Entity referencing collections of Entity

New Member 投稿: 1 参加年月日: 14/03/27 最新の投稿
Any on update on this? Do liferay now supports self referencing in Entities?