BaseGenericIdEntity example

Hi,

I have an entire ERP database where the tables are made with composite keys so I have two alternatives:

  1. fill the database tables with fields id (about four hundred … unfortunately)

  2. I have to try to manage the tables with composite keys

Trying to follow the choice 2 I see in the guide that there is BaseGenericIdEntity.

I have already created the @Embeddable class for the primary key … and then?

Unfortunately there is not much documentation in the guide.

I need an example, a classic case customer who has multiple addresses with a
composite key customer code string and address progressive numeric?

Thank you very much.

Maurizio.

Hi Maurizio,

Have you tried to use the Generate model wizard to create entities from your database automatically? It would give you examples of mapping to composite-key entities.

Hi Konstantin.

I will try to be clearer.

I have a table called ana10 for customer. I implemented it with an entity type BaseStringIdEntity with the key ana1001 of type String, and for the moment with only one field ana1010 description string.

Now I want to implement ana11 table for customer addresses in one-to-many with a composite key without UUID. Trying to create it with Cuba Studio I thought of using BaseGenericIdEntity but could not find this choice.

So I manually implemented in IntelliJ outside Cuba Studio Ana11PK the class for the primary key with annotations @Embeddable and Ana11 class for the entity.

I do not know if I’m doing things well done, but the Ana11 entities that I created in IntelliJ is not editable from Cuba Studio … so … I’m asking for help.

It 'a very important thing because once I found the correct way to implement the classes with composite keys I can start with the actual conversion project (buying the license of course).

I send you the entire modules package zipped so you can understand what I’m trying to do and where I’m wrong.

Thanks for your patience.

Maurizio.

modules.zip (11.7M)

OK, thank you. We’ll take a look.

Hi Konstantin,

I continued with my tests and I was able to develop Embeddable class Ana11PK and Ana11 entity class directly in Cuba Studio.

I have included Ana11 entities (addresses) Composition in parent Ana10 entities (customers) as a composition, and created the standard screen, everything seemed ok.

But now I have a runtime error when i open customer, that i can not solve.
I am attaching the current sources, ignore previous.

Thank you.

The exception is the following:


com.haulmont.cuba.core.global.RemoteException:
---
javax.persistence.PersistenceException: Exception [EclipseLink-6015] (Eclipse Persistence Services - 2.6.2.cuba11): org.eclipse.persistence.exceptions.QueryException
Exception Description: Invalid query key [ana1102] in expression.
Query: ReadAllQuery(name="ana11" referenceClass=Ana11 )
FetchGroup(ana11){ana10 => {class java.lang.Object=FetchGroup(ana10){ana1001, ana1010}}, ana1113 => {class java.lang.Object=FetchGroup(ana1113){tgn1301, tgn1310}}, ana1112, ana1111, id, ana1110}
---
org.eclipse.persistence.exceptions.QueryException: 
Exception Description: Invalid query key [ana1102] in expression.
Query: ReadAllQuery(name="ana11" referenceClass=Ana11 )
FetchGroup(ana11){ana10 => {class java.lang.Object=FetchGroup(ana10){ana1001, ana1010}}, ana1113 => {class java.lang.Object=FetchGroup(ana1113){tgn1301, tgn1310}}, ana1112, ana1111, id, ana1110}
	at com.haulmont.cuba.core.sys.ServiceInterceptor.aroundInvoke(ServiceInterceptor.java:93)
	at sun.reflect.GeneratedMethodAccessor112.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:629)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:618)
	at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:168)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
	at com.sun.proxy.$Proxy182.loadList(Unknown Source)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at com.haulmont.cuba.core.sys.remoting.LocalServiceInvokerImpl.invoke(LocalServiceInvokerImpl.java:95)
	at com.haulmont.cuba.web.sys.remoting.LocalServiceProxy$LocalServiceInvocationHandler.invoke(LocalServiceProxy.java:146)
	at com.sun.proxy.$Proxy22.loadList(Unknown Source)
	at com.haulmont.cuba.client.sys.DataManagerClientImpl.loadList(DataManagerClientImpl.java:52)
	at com.haulmont.cuba.gui.data.impl.GenericDataSupplier.loadList(GenericDataSupplier.java:100)
	at com.haulmont.cuba.gui.data.impl.CollectionDatasourceImpl.loadData(CollectionDatasourceImpl.java:542)
	at com.haulmont.cuba.gui.data.impl.CollectionDatasourceImpl.refresh(CollectionDatasourceImpl.java:148)
	at com.haulmont.cuba.gui.data.impl.CollectionDatasourceImpl.refresh(CollectionDatasourceImpl.java:106)
	at com.haulmont.cuba.gui.data.impl.CollectionDatasourceImpl.setSuspended(CollectionDatasourceImpl.java:651)
	at com.haulmont.cuba.gui.data.impl.DsContextImpl.resumeSuspended(DsContextImpl.java:83)
	at com.haulmont.cuba.gui.WindowManager.afterShowWindow(WindowManager.java:968)
	at com.haulmont.cuba.web.WebWindowManager.showWindow(WebWindowManager.java:398)
	at com.haulmont.cuba.web.WebWindowManager.lambda$showWindow$4(WebWindowManager.java:358)
	at com.haulmont.cuba.web.gui.WebWindow.close(WebWindow.java:1144)
	at com.haulmont.cuba.web.gui.WebWindow.closeAndRun(WebWindow.java:1032)
	at com.haulmont.cuba.gui.components.AbstractWindow.closeAndRun(AbstractWindow.java:289)
	at com.haulmont.cuba.web.WebWindowManager.showWindow(WebWindowManager.java:357)
	at com.haulmont.cuba.gui.WindowManager.openWindow(WindowManager.java:597)
	at com.haulmont.cuba.web.WebWindowManager.openWindow(WebWindowManager.java:137)
	at com.haulmont.cuba.gui.config.MenuCommand.execute(MenuCommand.java:100)
	at com.haulmont.cuba.web.sys.MenuBuilder$1.menuSelected(MenuBuilder.java:173)
	at com.vaadin.ui.MenuBar.changeVariables(MenuBar.java:207)
	at com.vaadin.server.communication.ServerRpcHandler.changeVariables(ServerRpcHandler.java:609)
	at com.vaadin.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:428)
	at com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:274)
	at com.vaadin.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:79)
	at com.haulmont.cuba.web.sys.CubaVaadinServletService$CubaUidlRequestHandler.lambda$synchronizedHandleRequest$112(CubaVaadinServletService.java:314)
	at com.haulmont.cuba.web.sys.CubaVaadinServletService.withUserSession(CubaVaadinServletService.java:196)
	at com.haulmont.cuba.web.sys.CubaVaadinServletService$CubaUidlRequestHandler.synchronizedHandleRequest(CubaVaadinServletService.java:314)
	at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:41)
	at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1424)
	at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:369)
	at com.haulmont.cuba.web.sys.CubaApplicationServlet.serviceAppRequest(CubaApplicationServlet.java:278)
	at com.haulmont.cuba.web.sys.CubaApplicationServlet.service(CubaApplicationServlet.java:187)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
	at com.haulmont.cuba.web.sys.CubaHttpFilter.handleNotFiltered(CubaHttpFilter.java:108)
	at com.haulmont.cuba.web.sys.CubaHttpFilter.doFilter(CubaHttpFilter.java:95)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
	at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:528)
	at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1099)
	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:672)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1520)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1476)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:745)

modules.zip (11.7M)

Maurizio,

It’s quite hard to find out the problem without ability to open the project in IDE and run it. Could you send us the whole project? You can press Alt+/ in Studio and select zipProject - an archive will be created in the project folder.

I realized that the problem seems to be include in the view, and then in the screen, the attributes of ana11 table that are part of EmbeddableEntity.

So ana1102 which is the address progressive code can not edit and even use as order by.

I hope to be able to explain the problem.

Thank you.

Here is the zipped project file.

Thanks again.

erp.zip (206.1K)

Hi Maurizio,

I have managed to make the Ana10-Ana11 composition work by doing the following:

  • In order to create the database, I had to comment out the duplicate ANA1101 varchar(16) field in ERP_ANA11 table. It is mistakenly added to the script by Studio because it doesn’t recognize the @MapsId(“ana1101”) annotation on the entity attribute. We’ll fix it in a nearest future version.

  • Added equals() and hashCode() methods to the Ana11PK primary key entity:


    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Ana11PK ana11PK = (Ana11PK) o;
        return Objects.equals(ana1101, ana11PK.ana1101) &&
                Objects.equals(ana1102, ana11PK.ana1102);
    }

    @Override
    public int hashCode() {
        return Objects.hash(ana1101, ana1102);
    }

  • Added a nested datasource and corresponding fields to edit embedded primary key in ana11-edit.xml editor screen:

    <dsContext>
        <datasource id="ana11Ds"
                    class="it.poloristorazione.erp.entity.Ana11"
                    view="ana11-view">
            <datasource id="ana11PKDs" property="id"></datasource>
        </datasource>
    </dsContext>
...
        <fieldGroup id="fieldGroup"
                    datasource="ana11Ds">
            <column width="250px">
                <field id="ana1101" datasource="ana11PKDs"></field>
                <field id="ana1102" datasource="ana11PKDs"></field>
                <field id="ana1110"></field>
                <field id="ana1111"></field>
                <field id="ana1112"></field>
                <field id="ana1113"></field>
                <field id="ana10"></field>
            </column>
        </fieldGroup>

However, keep in mind that you cannot edit primary key for an existing entity, so add code to disable these fields after creation of the entity.

Hope I listed all the changes. The whole project is attached.

erp.zip (206.3K)

Hi Konstantin,

I applied the changes you made. The program works correctly, the only question I have left is how to put order by ana1102 on the composition inside entity ana10.

I have left a few things to understand, the most important is that unfortunately I will have to see how to work with your framework and an Oracle version 8.1.7 for backward compatibility with the current erp; until now I have worked with mysql to understand the potential of Cuba.

I hope to bring the database used by erp to Oracle version 11 to solve the problem.

Anyway … I really want to thank you, Rostislav, Gleb and all the Cuba team for the help you are giving me. You have created a wonderful java framework, really powerful and I’m sure it’s the right tool to do the conversion of our old erp.

Thanks again.

Maurizio.

Hi Maurizio,

Thank you for your kind words, and I hope CUBA will help you to give new life to your application!

As for the ordering, the following should work:

  • Add @OrderBy(“id.ana1102”) to the List ana11 attribute of the Ana10 entity - it will set initial order of the collection

  • Fix the ana1102 column definition in ana10-edit.xml: it should be . So it will display the value correctly and allow users to sort the table.

Hi Konstantin,

I’m back for another doubt about composite keys. After solving the problem between ana10 ana11 and I try to do the same thing between ven20 and ven21 which are order header and order lines.

For my tests at the beginning I used BaseUuidEntity but unfortunately, as I had already written to you, the Oracle database is filled with composite keys and I can not change this.

Then:

Ven20PK order header is a key composed of three fields: type, year and number
Ven21PK order line is a key composed of Ven20PK plus the line number.

Cuba Studio will not let me define an attribute Ven20PK inside another EmbeddableEntity Ven21PK.

Maybe I’m wrong approach to the problem …

Be patient, please help me, thank you.

erp.zip (207.5K)

Hi Maurizio,

Things are getting more and more interesting :slight_smile:

We will probably add support for nested Embeddables to Studio, but it will take time. For now, could you try to create Ven21PK as an independent set of fields, duplicating the ones in Ven20PK?

Hi Konstantin,

when you say create ven21PK as an independent set of fields, you mean that after I have to use the @PrimaryKeyColumns annotation on the class?

And Cuba Studio supports these annotations or not … like @MapsId?

I do not have enough experience to find myself the right road and I do not want to go too far out from your standard, because otherwise the road becomes too rough …

So if you say that your standard necessarily involves a UUID instead of composite key I’ll have to add the id fields as I have already done for ven20 and ven21 in my test project.

Please show me what is the best way, according to your experience.

Thanks again.

Hi Maurizio,

If you can replace composite keys with UUID or Long keys, the further development of your application will be simpler and more straightforward. If you cannot do it because you have to keep compatibility with the legacy system or for some other reason - let us know and we’ll try to investigate this issue with nested composite key.

Hi Konstantin,

Thank you for your answer. I managed to build a model that seems to work. The problem I have right now is that when I move from browser to the orders edit order, I have the classic exception of detached entity.

I have no problems to enter the order lines, the problem occurs when I come back to see the rows inserted, it seems that the key entities ven21PK is detached.

The jpa model that I built appears to be correct and the rows are inserted correctly in the database

I will send the project so you can have a look and give me some help,
still a little effort and we should find the right way.

I am sure that together we can fix it and manage composite keys.

Thank you.

This is the exception:

IllegalStateException: Can not get unfetched attribute [ven2123] from detached object it.poloristorazione.erp.entity.Ven21-it.poloristorazione.erp.entity.Ven21PK@4ac0ff8 [detached]

erp.zip (301.2K)

:ticket: See the following issue in our bug tracker:

https://youtrack.cuba-platform.com/issue/STUDIO-3252