Hibernate ResultTransformer and gwt requestfactory

84 Views Asked by At

I created custom result transformer which extends BasicTransformerAdapter. In transformTuple method I create new object of Entity:

@Override
  public Object transformTuple(Object[] tuple, String[] aliases) {
    RegistryRow row = new RegistryRow();
    DataRow dataRow = new DataRow();
    Registry registry = new Registry();

    for (int i = 0; i < aliases.length; i++) {
      if ("id".equals(aliases[i])) {
        row.setId((Long) tuple[i]);
      } else if ("entityVersion".equals(aliases[i])) {
        row.setEntityVersion((Long) tuple[i]);
      } else if ("gridRowId".equals(aliases[i])) {
        dataRow.setId((Long) tuple[i]);
      } else if ("rowEntityVersion".equals(aliases[i])) {
        dataRow.setEntityVersion((Long) tuple[i]);
      } else if (tuple[i] != null && aliases[i] != null && aliases[i].startsWith("set")) {
        try {
          DataType type = DataRow.getDataType(tuple[i].getClass());
          Method m = DataRow.class.getMethod(aliases[i], type.getDataClass());
          m.invoke(dataRow, DataRow.castValue(tuple[i], type));
        } catch (Exception e) {
          LOG.error("--Error while setting dataRow data: ", e);
        }
      } else if ("registryCode".equals(aliases[i])) {
        registry.setCode((String) tuple[i]);
      } else if ("registryEntityVersion".equals(aliases[i])) {
        registry.setEntityVersion((Long) tuple[i]);
      }
    }

    row.setRegistry(registry);
    row.setGridRow(dataRow);

    return row;
  }

Everything works fine. There is created list of RegistryRow objects. On client side there is RegistryRowProxy which looks like this:

@ProxyFor(value = RegistryRow.class, locator = LongEntityLocator.class)
public interface RegistryRowProxy extends EntityProxy, BeanModelTag {

  Long getId();

  DataRowProxy getGridRow();

  Date getCreateDate();

  RegistryProxy getRegistry();

  Long getDataId();
}

It is used in gwt RequestFactory which calls list service.

getRequestFactory().registryRow().list(registry.getCode(), paramsId).with("gridRow").fire(receiver);

It returns data, everything is fine, but when I turn on show_sql it is doing additional selects to database. Queries like that:

select "all_columns" from RegistryRow where id = ?; 
select "all_columns" from DataRow where id = ?;

These queries are done as many times as there is rows in list. I don't know how to get rid off these additional queries which have influence on perfomance. Do you know why there are additional queries to database? (I add that in entity there are variables that looks like this:

@JoinColumn(name = "T_DATA_ROWS_ID")
  @NotNull
  private DataRow gridRow;

but not all of them)

Update 1: Annotation look like this exactly:

@OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)  
@JoinColumn(name = "T_DATA_ROWS_ID")  
@NotNull  
private DataRow gridRow;

And still it is doing queries for each row.

1

There are 1 best solutions below

1
Ümit On

You are telling RequestFactory to fetch a RegistryRowProxy and also retreive its gridRow subproperty (by using with("gridRow")).
So on your backend RequestFactory will internally call your getGridRow getter and this will cause Hibernate to (lazy) load the gridRow relationship.
To avoid the sub queries you need to tell Hibernate to eagerly load the relationship.
JPA should do this by default for @OneToOne and @ManyToOne relationships.

I assume your problem is that you are missing the @OneToOne annotation on your DataRow dataGrid property:

@JoinColumn(name = "T_DATA_ROWS_ID",nullable=false)
@NotNull
@OneToOne
private DataRow gridRow;