Hi, guys.
Please explain why Hibernate loads entities with batches of power of two elements? How it can be avoided?
To demonstrate this, I made test project with 3 entities: Owner, Car, Manufacturer.
Please see code of entities below:
Owner:Code:
@Entity(name = "com.github.karasik.entity.IOwner")
@Table(name = "OWNER")
@AttributeOverrides(value = {@AttributeOverride(name = "name", column = @Column(name = "OWNER_NAME"))})
public class OwnerDTO extends AbstractNamedEntityDTO implements IOwner {
    private Collection<ICar> cars;
    @Id
    @Column(name = "OWN_AA")
    public Integer getIdentifier() {
        return super.getIdentifier();
    }
    @OneToMany(mappedBy = "owner", targetEntity = CarDTO.class, cascade = CascadeType.ALL)
    @Override
    public Collection<ICar> getCars() {
        return cars;
    }
    @Override
    public void setCars(Collection<ICar> cars) {
        this.cars = cars;
    }
}
 Car:Code:
@Entity(name = "com.github.karasik.ICar")
@Table(name = "CAR")
@AttributeOverrides({@AttributeOverride(name = "name", column = @Column(name = "CAR_NAME"))})
public class CarDTO extends AbstractNamedEntityDTO implements ICar {
    private IOwner owner;
    private IManufacturer manufacturer;
    @Id
    @Column(name = "CAR_AA")
    @Override
    public Integer getIdentifier() {
        return super.getIdentifier();
    }
    @Override
    @ManyToOne(targetEntity = OwnerDTO.class)
    @JoinColumn(name = "CAR_OWN_AA")
    public IOwner getOwner() {
        return owner;
    }
    @Override
    public void setOwner(IOwner owner) {
        this.owner = owner;
    }
    @ManyToOne(targetEntity = ManufacturerDTO.class)
    @JoinColumn(name = "CAR_MAN_AA")
    @Fetch(FetchMode.SELECT)
    @Override
    public IManufacturer getManufacturer() {
        return manufacturer;
    }
    @Override
    public void setManufacturer(IManufacturer manufacturer) {
        this.manufacturer = manufacturer;
    }
}
Manufacturer:Code:
@Entity(name = "com.github.karasik.entity.IManufacturer")
@Table(name = "MANUFACTURER")
@AttributeOverrides({@AttributeOverride(name = "name", column = @Column(name = "MAN_NAME"))})
public class ManufacturerDTO extends AbstractNamedEntityDTO implements IManufacturer {
    @Id
    @Column(name = "MAN_AA")
    @Override
    public Integer getIdentifier() {
        return super.getIdentifier();
    }
}
I have this Database CAR table structure:
Code:
 efim=# select * from car;
 car_aa | car_name | car_man_aa | car_own_aa 
--------+----------+------------+------------
      1 | Car 1    |          1 |          1
      2 | Car 2    |          2 |          1
      3 | Car 3    |          3 |          1
      4 | Car 4    |          4 |          1
      5 | Car 5    |          5 |          1
      6 | Car 6    |          6 |          1
      7 | Car 7    |          7 |          1
      8 | Car 8    |          8 |          1
      9 | Car 9    |          9 |          1
     10 | Car 10   |         10 |          1
     11 | Car 11   |         11 |          1
(11 rows)
When using Hibernate I load from DB Owner record with own_aa=1 and then initialize Cars collection:
Code:
    
public Integer getCarCount(Integer manufacturerAa) {
    IOwner owner = dao.find(OwnerDTO.class, manufacturerAa);
    return owner.getCars().size();
}
Hibernate needs to load 11 car entities.
Please note, it makes two queries to load manufacturers (Fetch=SELECT):
Code:
    select
        cars0_.CAR_OWN_AA as CAR_OWN_3_2_1_,
        cars0_.CAR_AA as CAR_AA1_0_1_,
        cars0_.CAR_AA as CAR_AA1_0_0_,
        cars0_.CAR_MAN_AA as CAR_MAN_2_0_0_,
        cars0_.CAR_OWN_AA as CAR_OWN_3_0_0_ 
    from
        CAR cars0_ 
    where
        cars0_.CAR_OWN_AA=?
    select
        manufactur0_.MAN_AA as MAN_AA1_1_0_ 
    from
        MANUFACTURER manufactur0_ 
    where
        manufactur0_.MAN_AA in (
            ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
        )
    select
        manufactur0_.MAN_AA as MAN_AA1_1_0_ 
    from
        MANUFACTURER manufactur0_ 
    where
        manufactur0_.MAN_AA=?
 For some reason instead of fetching 11 manufacturers via single query, Hibernate makes two queries.
From source code I can see, that loading is performed in batches of 1,2,...,10,16,32,64,128,...,
hibernate.default_batch_fetch_size entities.
Could you please advice how can I change Hibernate behavior not to perform two queries for 10 and 1 element but to make single query for 11 elements?
I wonder why Hibernate fetching behavior was made this way. An explanation will be very helpful.
Sorry if this question is a duplicate or a well known Hibernate feature.
Thanks a lot!