简体   繁体   中英

JPA relationship JPAContainer with ComboBox?

I'm looking for a way to use a jpa relationship @OneToMany/@OneToOne/@ManyToOne/@ManyToMany with a ComboBox.

@Entity
public class State {

    @Id
    @GeneratedValue
    private Integer id;

    @NotNull @NotEmpty @Size(min=5, max=50)
    private String state;

    @OneToOne
    private Governor governor;

}

@Entity
public class Governor {

    @Id
    @GeneratedValue
    private Integer id;

    @NotNull @NotEmpty @Size(min=5, max=50)
    private String governor;

}

//app
public class StateView extends VerticalLayout {
    //jpacontainer
    private final CustomJPAContainer<State> datasource = new CustomJPAContainer<State>(State.class);

    //attributes
    private String state;
    private ComboBox governor;
    private final BeanFieldGroup<State> binder = new BeanFieldGroup<State>(State.class);
    private State bean = new State();


    public StateView(){
         Field<?> field = null;

         //state
         field = binder.buildAndBind("State", "state");
         state = binder.getField("state");
         vLayout.addComponent(state);

         //combo governor
         here, how to create combobox to governor relationship ?

    }
}

How I do to create a combobox with this relationship using JPAContainer ?

Edited*

/** datasources */
private final CustomJPAContainer<State> datasource = new CustomJPAContainer<State>(Curriculum.class);
private final CustomJPAContainer<Governor> dsGovernor = new CustomJPAContainer<Governor>(Governor.class);

//governor combobox
field = binder.buildAndBind("Governor", "governor", ComboBox.class);        
governor = (ComboBox)binder.getField("governor");
governor.setContainerDataSource(dsGovernor);        
governor.setItemCaptionPropertyId("governor");      
governor.setImmediate(true);
governor.select(0);
vLayout.addComponent(governor);

//button click
binder.commit()

When I try commit, return this error.

com.vaadin.data.fieldgroup.FieldGroup$CommitException: Commit failed
    at com.vaadin.data.fieldgroup.FieldGroup.commit(FieldGroup.java:463)
    at br.ind.ibg.views.StateView.buttonClick(StateView.java:142)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:508)
    at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:198)
    at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:161)
    at com.vaadin.server.AbstractClientConnector.fireEvent(AbstractClientConnector.java:969)
    at com.vaadin.ui.Button.fireClick(Button.java:368)
    at com.vaadin.ui.Button$1.click(Button.java:57)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:168)
    at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:118)
    at com.vaadin.server.communication.ServerRpcHandler.handleBurst(ServerRpcHandler.java:207)
    at com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:111)
    at com.vaadin.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:91)
    at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:37)
    at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1382)
    at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:238)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:313)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:724)
Caused by: com.vaadin.data.Buffered$SourceException
    at com.vaadin.ui.AbstractField.commit(AbstractField.java:251)
    at com.vaadin.data.fieldgroup.FieldGroup.commit(FieldGroup.java:443)
    ... 43 more
Caused by: com.vaadin.data.util.converter.Converter$ConversionException: Could not convert value to Governor
    at com.vaadin.ui.AbstractField.convertToModel(AbstractField.java:748)
    at com.vaadin.ui.AbstractField.convertToModel(AbstractField.java:725)
    at com.vaadin.ui.AbstractField.getConvertedValue(AbstractField.java:811)
    at com.vaadin.ui.AbstractField.commit(AbstractField.java:247)
    ... 44 more
Caused by: com.vaadin.data.util.converter.Converter$ConversionException: Unable to convert value of type java.lang.Integer to model type class br.ind.ibg.beans.Governor. No converter is set and the types are not compatible.
    at com.vaadin.data.util.converter.ConverterUtil.convertToModel(ConverterUtil.java:181)
    at com.vaadin.ui.AbstractField.convertToModel(AbstractField.java:745)
    ... 47 more

A straight forward solution:

BeanItemContainer<State> container = new BeanItemContainer<State>(State.class);

final BeanFieldGroup<State> binder = new BeanFieldGroup<State>(State.class);
binder.setFieldFactory(new DefaultFieldGroupFieldFactory() {

    @SuppressWarnings("unchecked")
    @Override
    public <T extends Field> T createField(Class<?> type, Class<T> fieldType) {

        if (type.isAssignableFrom(Governor.class) && fieldType.isAssignableFrom(ComboBox.class)) {
            return (T) new ComboBox(); // we create a ComboBox for the Governor property
        }

        return super.createField(type, fieldType);
    }

});

final State bean = new State();

Field<?> field = null;
binder.setItemDataSource(bean);

binder.buildAndBind("State", "state");
field = binder.buildAndBind("Governor", "governor", ComboBox.class);

ComboBox cmbx = (ComboBox) field;

// We define a container data source for your Governors.
// I've taken the BeanItemContainer
cmbx.setContainerDataSource(new BeanItemContainer<Governor>(Governor.class));

// If you want to use a JPAContainer you need to translate entities to identifiers and visa versa
// cmbx.setContainerDataSource(dsGovernor);
// cmbx.setConverter(new SingleSelectConverter<Governor>(cmbx));
cmbx.setItemCaptionPropertyId("governor");

// we create two dummy Governors
Governor governorA = new Governor();
governorA.setGovernor("A");
Governor governorB = new Governor();
governorB.setGovernor("B");

// ... and add them to the container
cmbx.getContainerDataSource().addItem(governorA);
cmbx.getContainerDataSource().addItem(governorB);

// when the binder is committed the value of the ComboBox ( getValue() )is mapped to our state bean.

This question is related to another question on Stackoverflow: Vaadin 7.0.1 Combobox with JPAContainer and FieldGroup .

I wrote a blog post about this topic which explains how FieldGroups work internally and how you can make them work for this particular use case: Select Nested JavaBeans With a Vaadin FieldGroup . This post will also explain why a ConversionException is thrown in your example.

Of course you could switch to using a BeanItemContainer , but by using a simple Converter implementation you can use any Container implementation as data source for your ComboBox. See the blog post for details.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM