Binding foreign key in Vaadin (EclipseLink)

2019-08-30 07:09发布

问题:

I'm using Vaadin and EclipseLink. There are 2 tables, one is Mail, second in Customer. PK for Customer is customer_id, PK for mail is mail_id. Table Mail has Customer_id as a foreign key. How do I bind it? I tried:

binder.forField(fkCustomerId)
        .withConverter(new StringToBigDecimalConverter(FormMessages.NUMBERS_ONLY))
        .bind(Mail::getCustomerId, Mail::setCustomerId);

Then I checked the Mail-entity class and found

@JoinColumn(name = "CUSTOMER_ID", referencedColumnName = "CUSTOMER_ID")
@ManyToOne
private Customer customerId;

I checked this page - https://vaadin.com/docs/v8/framework/datamodel/datamodel-forms.html but there was nothing about fk binding.

回答1:

Option 1: Convert customer ID

Here I am assuming that ID field on Customer class is called id and that it is of type Long. This allows you to access that ID field through converter that produces unformatted string presentation. Note that this does not handle null value nicely.

binder.forField(fkCustomerId)
        .withConverter(Long::valueOf, String::valueOf)
        .bind("customerId.id");

Option 2: Convert customer object

This example would take Customer object and convert that to desired format for the customer ID field. This allows you to handle null values and do more advanced formatting based on state of the whole object.

binder.forField(fkCustomerId)
        .withConverter(new CustomerToCustomerIdConverter())
        .bind(Mail::getCustomerId, Mail::setCustomerId);

You can omit convertToModelresult in the converter because you should not be creating customer objects from ID values that user types.

public class CustomerToCustomerIdConverter implements Converter<String, Customer> {
    @Override
    public Result<Customer> convertToModel(String s, ValueContext valueContext) {
        return Result.error("not supported");
    }

    @Override
    public String convertToPresentation(Customer customer, ValueContext valueContext) {
        return Objects.toString(customer.getCustomerId(), "");
    }
}

TextField style

In order to setup TextField style, you need to set it to read-only mode. And if you do not want to get the text field border at all then you need to add extra style.

TextField fkCustomerId = new TextField();
fkCustomerId.addStyleName(ValoTheme.TEXTFIELD_BORDERLESS);
fkCustomerId.setReadOnly(true);