留言板

Liferay Service Builder Primary Key with Autoincrement

Varun Arya,修改在6 年前。

Liferay Service Builder Primary Key with Autoincrement

New Member 帖子: 24 加入日期: 17-3-2 最近的帖子
Hi,
I am using service builder to my all plugin portlets. And i have custom table having primary key with autoincrement.
As of now i know there are these ways to insert records to table.

XXX xxx = XXXLocalServiceUtil.createXXX(0);
xxx.setValue(value);
XXXLocalServiceUtil.addXXX(xxx);

OR

XXX xxx = XXXLocalServiceUtil.createXXX(CounterLocalServiceUtil.increment()); // Global increment
xxx.setValue(value);
XXXLocalServiceUtil.addXXX(xxx);

OR

XXX xxx = XXXLocalServiceUtil.createXXX(CounterLocalServiceUtil.increment(XXX.class.getName())); // Increment table specific
xxx.setValue(value);
XXXLocalServiceUtil.addXXX(xxx);

In first if i want to get promary key value i gets 0, second long value, third incremented value wrt table name.
I am using thid one. Now if i re-deploy the service or portlet counter value will be incresed 101,201,...
And this can be handled by setting counter.increment.xxx.Class=1 or counter.increment=1.

But i just want to get database table incremented value from "xxx". So there is any way to do this.
Like this:
XXX xxx = new XXXImpl();
xxx.setValue(value);
XXXLocalServiceUtil.addXXX(xxx);
Here i can get the value which i want from database table.
thumbnail
Andrew Jardine,修改在6 年前。

RE: Liferay Service Builder Primary Key with Autoincrement

Liferay Legend 帖子: 2416 加入日期: 10-12-22 最近的帖子
Hi Varun,

I'm totally confused as to what you are asking -- but I will tell you that the convention, generally, is to use either option #2 (the global increment) or option #3 for your custom entities. Setting the counter increment to 1 will affect ALL counters and the down side is that, with a value that low, you can suffer a performance impact in high transactional systems. If there is a specific value that you need to have then I would suggest one of two options.

1. Just set the value yourself --

long myKey = 1234;
XXX var = XXXLocalServiceUtil.getXXX(myKey)


or alternatively,

2. use a separate column for the id that you require so that the xxxId can be whatever Liferay assigns and you use your fkId column (assuming you need a certain value for a FK or sorts) in your code to reference your other data. You can then you the increment mechanism, but then manually assign your fk.

If you us the first method, I would suggest doing it in the Impl for your service that that you can centralize the logic rather than using it in (possibly) several places and having to do multiple updates later.
Varun Arya,修改在6 年前。

RE: Liferay Service Builder Primary Key with Autoincrement

New Member 帖子: 24 加入日期: 17-3-2 最近的帖子
Hi Andrew,

Thanks for the help. I found my answer where i was stuck.
thumbnail
David H Nebinger,修改在6 年前。

RE: Liferay Service Builder Primary Key with Autoincrement (答复)

Liferay Legend 帖子: 14919 加入日期: 06-9-2 最近的帖子
Varun Arya:
i have custom table having primary key with autoincrement. As of now i know there are these ways to insert records to table.


Well, no, you know of the one right way to do it (using createXxx(0)) and two incorrect ways of doing it (using CounterLocalServiceUtil, doubly wrong because your instance will have a counterLocalService reference that you're not using and you're violating the rule of using the LocalServiceUtil classes inside of the service layer).

When you use autoincrement, you're deferring to Liferay to assign the primary key. When you pass in the special value 0, Liferay uses this as a flag that the new value should be assigned.

In first if i want to get promary key value i gets 0, second long value, third incremented value wrt table name. I am using thid one. Now if i re-deploy the service or portlet counter value will be incresed 101,201,... And this can be handled by setting counter.increment.xxx.Class=1 or counter.increment=1.


That is an artifact of the counter local service handling. The normal "block" of next sequence numbers are retrieved in 100s. So the first deployment the block starting from 101 through 200 is retrieved and cached. As new records are entered, they will get the next value from the block so you will find records assigned as 101, 102, 103, ...

On the next deployment (or app server restart), the counter local service doesn't know which ids from the previous block were used, so it starts with a new block, 201 through 300, to assign from there. Each new redeploy or restart will result in a new block.

But i just want to get database table incremented value from "xxx". So there is any way to do this. Like this:
XXX xxx = new XXXImpl();
xxx.setValue(value);
XXXLocalServiceUtil.addXXX(xxx);
Here i can get the value which i want from database table.


First you should never, ever be doing new XXXImpl() directly. You never know if Liferay might change the underlying code to create a new instance and your code would all of a sudden break with no clear reason why.

Just stick with the "Xxx xxx = createXXX(0);" form.

Now it sounds like you're actually asking about the ID type "sequence" which defers to a database assigned key value. Start by checking the Liferay service builder DTD file to get the details on the sequence assignment and what databases are supported by sequences.

You still use the "createXXX(0)" form to create a new instance, but your problem is that you are not using the value returned by the addXXX() call.

When you do "xxx = addXXX(xxx);", xxx will be reassigned the value from the add call where the sequence value would be assigned and returned.

Also with the continuing use of XxxLocalServiceUtil, it looks like you are doing this kind of thing outside of the service layer.

The purpose of your service layer is to encapsulate (hide) service implementation details. Like this one for example. Outside code shouldn't care whether you need to use a zero, assign by a counter or are relying on a sequence value to assign the ids. Outside code just needs to insert a new record given a list of parameters.

That's why you'll see that Liferay code commonly has some sort of addXxx() method in the XxxLocalServiceImpl class that takes a list of parameters as arguments. Inside the body of the addXxx() method, that is where the createXxx(0) followed by the setter calls and finishing with a "return addXxx(xxx);" to complete the addition of the new object.










Come meet me at Devcon 2017 or 2017 LSNA!
Varun Arya,修改在6 年前。

RE: Liferay Service Builder Primary Key with Autoincrement

New Member 帖子: 24 加入日期: 17-3-2 最近的帖子
Thank you David, It really works for me. I just need the primary key.

XXX xxx = XXXLocalServiceUtil.createXXX(0);
xxx.setValue(value);
xxx=XXXLocalServiceUtil.addXXX(xxx);


It works. emoticon Thank you so much.
Zak Thompson,修改在6 年前。

RE: Liferay Service Builder Primary Key with Autoincrement

Junior Member 帖子: 70 加入日期: 16-6-13 最近的帖子
David H Nebinger:

Well, no, you know of the one right way to do it (using createXxx(0)) and two incorrect ways of doing it (using CounterLocalServiceUtil, doubly wrong because your instance will have a counterLocalService reference that you're not using and you're violating the rule of using the LocalServiceUtil classes inside of the service layer).


Is there a performance hit or some other downside to using Utils within ServiceBuilder impls?
thumbnail
David H Nebinger,修改在6 年前。

RE: Liferay Service Builder Primary Key with Autoincrement

Liferay Legend 帖子: 14919 加入日期: 06-9-2 最近的帖子
Yes, but hardly measurable.

I mean, if you call a static util class it uses a getter to fetch the service reference and then pushes all of the arguments to invoke the reference.

So there is some time involved with that and I'm sure we could build a test harness out to determine the impact by iterating over thousands of calls, but for single calls the impact is insignificant.

That said, it doesn't mean that it should be ignored. Performance, after all, is measured upon load to you system, the ability to handle tens of thousands, hundreds of thousands or even millions of calls per sec. Under that kind of load, everything becomes measurable.

So instead of coming back later on to address performance issues, it's always a best practice to do what you can up front. Using the @Reference is the best path for performance purposes, plus it should help if at some point in the future Liferay decides they don't need the static classes anymore since @Reference injection works everywhere.

The Util classes are there mostly for legacy support, but at some point legacy just seems to fall away, right?






Come meet me at Devcon 2017 or 2017 LSNA!