Howdy, Hibernators. I'm having a problem whereby I find myself too unskilled with Hibernate to implement an @ManyToMany association mapping that generates anything other than a left outer join. This is unfortunately against a fairly large table, which is yieldinging unacceptable performance. Nothing I have tried changes the underlying query to be an inner join, which I believe should be the sort of SQL generated in this case. Here are my specifics:
Hibernate version:
Hibernate Core 3.2.4.SP1
Hibernate Annotations 3.3.0.GA
Name and version of the database you are using:
Micro$oft $QL-$erver 2005
My guesses at relevant mapping annotations
There are only 2 entities involved in the problem I am having, Function (which holds info for a Functional Area of our company) and HrProfile (which holds personal information is hydrated from a legacy table maintained by a non-hibernate-using team). HrProfile is an immutable hombre and he doesn't have any associations to Function. Function, however has the notion of default owners of that function, which I chose to implement as a unidirectional Many-To-Many with HrProfile.
The Function class is annotated as:
Code:
@Entity
@Table( name = "Functions" )
public class Function implements Dumpable, SimpleAuditAware
So no surprises, there. The property of Function that implements the association is:
Code:
@ManyToMany( cascade = CascadeType.ALL, fetch = FetchType.LAZY )
@JoinTable( name = "FunctionsToDefaultOwners",
joinColumns = { @JoinColumn( name = "FunctionId", nullable = false ) },
inverseJoinColumns = { @JoinColumn( name = "Emplid", nullable = false ) } )
@OrderBy( "lastName" )
private Set<HrProfile> getDefaultOwners()
Yes, I know the property is private, but I have a transient public property that exposes an immutable copy of the collection, so users of my class have to go thru the class to mutate the collection.
The generated SQL (show_sql=true):Code:
select
defaultown0_.FunctionId as FunctionId1_, defaultown0_.Emplid as Emplid1_,
hrprofile1_.emplid as emplid0_0_, hrprofile1_.DeptName as DeptName0_0_,
hrprofile1_.DisplayFirstName as DisplayF3_0_0_, hrprofile1_.EmailAddress as EmailAdd4_0_0_,
hrprofile1_.EmplStatus as EmplStatus0_0_, hrprofile1_.LastName as LastName0_0_,
hrprofile1_.PreferredFirstName as Preferre7_0_0_, hrprofile1_.JobTitle as JobTitle0_0_,
hrprofile1_.WorkPhone as WorkPhone0_0_, hrprofile1_.FirstName as FirstName0_0_,
hrprofile1_.FirstNameSearch as FirstNa11_0_0_, hrprofile1_.Name as Name0_0_,
hrprofile1_.LastNameSearch as LastNam13_0_0_, hrprofile1_.SupervisorId as Supervi14_0_0_
from
FunctionsToDefaultOwners defaultown0_
left outer join
Employees hrprofile1_
on defaultown0_.Emplid=hrprofile1_.emplid
where
defaultown0_.FunctionId=?
order by
hrprofile1_.LastName asc
I originally didn't have the nullable annotation parameters in there for the @JoinColumns, and I truly thought that adding them would change the generated SQL from a left outer join to some sort of inner join, but this is not the case.
Can anybody out there share some wisdom on something that I have missed? Alternatively, can someone with experience with associating with fairly large legacy tables share some wisdom on a better strategy for implementing that sort of thing in Hibernate?