Fix performance regression on preloading HABTM associations

We'd spend a lot of time calling `hash` and `eql?` on the join model,
which has no primary key. Calling `id` with no primary key is a really
slow way to get back `nil`, so we can improve the performance there.
However, even with the escape clause, we *still* weren't getting high
enough performance, as we were checking the primary key too much. `hash`
will always return `nil.hash` for records with no id, and `==` will
always return `false`. We can optimize those cases in the HABTM join
model.

Fixes #15663
Consider using a conditional rather than an early return:
```ruby
if pk = self.class.primary_key
  sync_with_transaction_state
  read_attribute pk
end
```
Turns the code into a single expression "if there's a primary key, read it" rather than an imperative check "if there isn't a primary key, stop; read the primary key"