Generating a Long hash for a case class

Hi there. I’m looking for a way to define a function that is nearly identical to hashCode but which returns a Long instead of an int. My use case for this is that I’m modeling entities which will be inserted into a database, and I would like to derive the key of each entity based on its contents. Ultimately, I think this problem could boil down to something like this:

// I need something which can hash a Product to support tuples or case classes
def hashProduct(value: Product): Long = ???

case class Entity private(dataA: String, dataB: String, id: Long)

object Entity {
  def apply(dataA: String, dataB: String): Entity = 
    new Entity(dataA, dataB, hashProduct((dataA, dataB)))
}

val entity = Entity("Hello", "world")
val entityId: Long = entity.id

Is there an easy way to do this?

Some more details of my problem, to avoid X-Y confusion:

I have two entity types I would like to insert into a database which have a many-to-many relationship.
I would like to batch insert the entities and their relationships to one another. I’m currently using
auto-incrementing primary keys for the entities, meaning that I don’t know the ID of an entity until after I’ve inserted it. This breaks the batching requirement since I’d need at least two round-trips to the database:
one for inserting the entities and receiving their IDs, and one for inserting the relationships between those
entities’ IDs.

My new plan is to ditch the auto-incrementing IDs and replace them with keys derived from the Entity
data. I’d like the generated key to be deterministic and range over the full Long space, 64 bits. The
ergonomics of Java’s hashCode is exactly what I want (e.g. if I could call (dataA, dataB).hashCode()) that would be perfect), except for the fact that it’s locked into Int.

Any help or suggestions on this would be greatly appreciated!

Case classes happen to extend Product, which I believe you can use to create a hashProduct function like you describe (not tested):

def hashProduct(p: Product): Long =
(0 to (p.productArity-1)).foldLeft(0L)( (hash, idx) => foldIn(hash, p.productElement(idx).hashCode)
def foldIn(hash: Long, elementHash: Int): Long = …your creative accumulation of (Long, Int) => Long here…

Best regards,

Brian Maso