Wrapping PersistentSet of one-to-many relationship throws error during Annotation based mapping where as no error is thrown in xml based mapping

In our codebase, we use xml file for mapping entities to tables. This was created back in 2010.
Eventually for some of our one-to-many relationship b/w entities we introduced a wrapper over PersistentSet.

One such instance where two entities, ConfigContainer.java and Config.java are related by one-to-many association:

  <class name="org.namespace.ConfigContainer"
         table="CONFIG_CONTAINERS">

    <id name="id" column="CONFIG_CONTAINER_ID">
      <generator class="native"/>
    </id>
    <version name="optimisticLockVersion"
             column="OPTIMISTIC_LOCK_VERSION"
             type="long"/>
    <property name="configType" column="CONFIG_TYPE" not-null="true" unique="true"/>

    <!-- Configs are saved via cascade but are deleted explicitly. -->
    <set name="configsForDb" inverse="true" cascade="save-update,merge,persist">
      <key column="CONFIG_CONTAINER_ID"/>
      <one-to-many class="org.namespace.Config"/>
    </set>

    <property name="configGeneration" column="CONFIG_GENERATION" not-null="true"/>
  </class>


    <class name="DbConfig" table="CONFIGS">
    <id name="id" column="CONFIG_ID">
      <generator class="native"/>
    </id>

    <version column="OPTIMISTIC_LOCK_VERSION" name="optimisticLockVersion" type="long" />

    <many-to-one name="configContainer"
                 column="CONFIG_CONTAINER_ID"
                 class="org.namespace.DbConfigContainer"
                 foreign-key="FK_CONFIG_CONFIG_CONTAINER"
                 index="IDX_CONFIG_CONFIG_CONTAINER"/>
  </class>

POJO for ConfigContainer.java is :

public class ConfigContainer  {

  private Wrapper<Config> configs = new Wrapper<Config>(Sets.<DbConfig> newHashSet());

    /**
   * Hibernate uses this to pass in a PersistentSet object (which
   * loads things lazily.  We wrap it a bit, but make sure to give
   * back the original object, too.
   */
  public void setConfigsForDb(Set<Config> configs) {
    this.configs = new Wrapper<Config>(configs);
  }

  public Set<DbConfig> getConfigsForDb() {
    return configs.delegate();
  }

}

The above Wrapper.java is basically a cache which stores the configs. I can more info if you want.

We are currently facing Performance issues 1.

We want to ask the above problem in this community again. So we are first creating a dummy project modelling such entities. But this time we are using Annotations instead of xml for mapping.

Here is ConfigContainer.java in our dummy project using Annotations.

@Entity
@Table(name = "CONFIG_CONTAINERS")
public class ConfigContainer {

	@OneToMany(cascade=CascadeType.ALL, mappedBy="configContainer")
	private Wrapper<DbConfig> configs =
			new Wrapper<>(new HashSet<DbConfig>());

	public void setConfigsForDb(Set<Config> configs) {
		this.configs = new Wrapper<>(configs);
	}

	public Set<Config> getConfigsForDb() {
		return configType.delegate;
	}  
}

But when I run the code, the following exceptions were thrown:

org.namespace.Wrapper collection type not supported for property: org.namespace.ConfigContainer.configs
Custom type does not implement UserCollectionType: org.namespace.Wrapper

I know the solution is to make the Wrapper.java implement UserCollectionType 2

My question is, why I am not getting the same error in my actual codebase ? In actual codebase, the Wrapper.java class doesn’t implement UserCollectionType. Also I have grep-ed my entire codebase but didn’t find any usages of UserCollectionType. How is it working in xml based mapping.

Hibernate-version: 5.4.27.Final

You have to annotate the getter getConfigsForDb with @OneToMany to get the same configuration.

1 Like