RE: Expando rows

Mk Sin, modified 13 Years ago. Junior Member Posts: 74 Join Date: 5/25/12 Recent Posts
I want to create an expando table with values are organizationids and its specify key of each user
I have User, long[] orgIds, String[] key
so it would be:
User A:

                 organizaionid                           key
                  123                                    red
                  456                                    green

....
i have no exp with expando, i dont know how to create multi rows for one user
i tried with code:
ExpandoBridge expandoBridge = user.getExpandoBridge();
//each key have same default values list
		expandoBridge.setAttributeDefault(UserExpando.KEY.getName(), new String[]{"red","green","blue"});
//set expando values
		expandoBridge.setAttribute(UserExpando.ORG_ID.getName(), organizationIds[0]);
		expandoBridge.setAttribute(UserExpando.KEY.getName(), keys[0]);

but it seem be created only one row and will overwrite all to one if i use loop

this is UserExpando
	// Public Enumeration
	ORG_ID("orgid"), KEY("key");

	// Private Constants
	private static final String MODEL_CLASS_NAME = User.class.getName();

	// Private Data Members
	private int expandoType;
	private boolean indexable;
	private String name;

	private UserExpando(String name) {
		this(name, ExpandoColumnConstants.STRING, true);
	}
//getter and setter


Can i get the key value, if i have the User and orgid ?
Can i create multi rows expando with orgid as primary key for each User ?
Can anybody give me some suggestion ?! please!
thumbnail
David H Nebinger, modified 13 Years ago. Liferay Legend Posts: 14933 Join Date: 9/2/06 Recent Posts
I think you have interpreted expando incorrectly...

Expando is meant to allow you to expand one of the canned Liferay tables to virtually add additional columns to the table. The standard use case is the User object where you want to add additional fields. Like if you wanted to capture the name of the high school the user attended, Expando is an appropriate way to do this.

Expando is not meant to accept new relations however. What you're describing is a new relationship and would therefore require a separate table to implement.
thumbnail
Steve Weiss, modified 5 Years ago. Regular Member Posts: 112 Join Date: 9/20/11 Recent Posts
I'm working with the expando API and came across this thread. We have a portlet that uses ckeditor to create a form. Each instance of the portlet has its own form. When the form is created, we (in LR 6.2) create a new database table to hold data collected by users who fill out the form. This database lives outside LR. Now that we're moving to LR 7.2 I want to bring this inside liferay (rather than using JDBC) so I've started to implement it using the Expando API. So when a new form is created I create a new ExpandoTable, and I want to populate it with data users submit from the form.

David's response above suggests that this may not work, and in fact I'm running into a problem- creating an ExpandoRow requires a PK, as does creating an ExpandoValue. In our case, there is no PK since these records do not relate to anything in the LR database. It's just data submitted from a form. The current system has multiple tables holding data from multiple forms that were created in different portlet instances.

So the question now is, will this work? I'm getting constraint violations trying to add a new row with the same PK.  Could I just use any unique (in that one table) number as a phony PK?
thumbnail
David H Nebinger, modified 5 Years ago. Liferay Legend Posts: 14933 Join Date: 9/2/06 Recent Posts
It can work, you can fake out PK values easily enough.

The question, though, is whether you should do this or not.

With expandos, it's not a single row per form or anything like that. It is a single row per "logical column" in your dataset. So if you logically have a table with 15 columns, then you actually have 15 rows in the values table, one for each column.

As storage mechanisms go, this is really poor performing, plus it has limited query and index capabilities, so the whole performance of this implementation would be terrible.

A better alternative would be to leverage the Liferay forms API. That at least converts a single logical "row" of data into a JSON string that is persisted, so you get back to one DB row per logical record. And if you're going to go this route, you might rethink how the form is created in the first place since the Liferay form builder in 7.2 is significantly better than in older versions; you could replace all of your custom portlet code with an OOTB Liferay Forms implementation.