Home > Software engineering >  Make Hibernate use a different List wrapper than PersistentBag
Make Hibernate use a different List wrapper than PersistentBag

Time:05-20

The Problem with PersistentBag is that it violates the Collections API equals() contract, which breaks unit test assertions via AssertJ's containsExactlyInAnyOrder(). Hibernate also has different wrapper implementations such as PersistentList, is there a way to force Hibernate (version 5.6.7) to use those instead of PersistentBag?

@Entity
data class AnalysisType(
    @Id
    name: String,

    @Column(name = "reference_type")
    @OneToMany(fetch = LAZY, cascade = [])
    val referenceTypes: List<ReferenceType>
)

@Entity
data class ReferenceType(
    @Id
    val id: Long,

    @Column
    val name: String
)

CodePudding user response:

I think there's something wrong with the unit tests. Comparing two collections using an equals doesn't seem the right approach. In particular, when using unordered lists, elements might not always be in the same order.

You also need to make sure that you've implemented the correct hashcode/equals for the entities. In java, for ReferenceType, it should look like:

        @Override
        public boolean equals(Object o) {
            if ( this == o ) {
                return true;
            }
            if ( !( o instanceof ReferenceType ) ) {
                return false;
            }
            ReferenceType rt = (ReferenceType) o;
            return Objects.equals( name, rt.name );
        }

        @Override
        public int hashCode() {
            return Objects.hash( name );
        }

That said, if you want to have a PersistentList, the mapping needs to reflect an ordered list. You can achieve this using @OrderColumn:

@Entity(name = "Person")
public static class Person {

    @Id
    private Long id;

    @OneToMany(cascade = CascadeType.ALL)
    @OrderColumn
    private List<Phone> phones = new ArrayList<>();

    //Getters and setters are omitted for brevity

}

You can find more in the Hibernate ORM documentation in the section about collections of entities.

CodePudding user response:

If you are using containsExactlyInAnyOrder from assertj the order of the elements does not matter. You can check for duplicates. If the PersistentBag contains the same element twice you should use containsOnly which does not care about the order and is ignoring duplicates. The equals method on the PersistentBag should not matter too because the contains... assertions in assertj are comparing element by element for the collections.

It looks like they may be sth wrong in your tests. Can you post assertj message?

  • Related