Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I auto-generate a GUID for a join table?

I'm using Hibernate 4.1.0.Final, JPA 2.0, and MySQL 5.5. I have the following entity:

@GenericGenerator(name = "uuid-strategy", strategy = "uuid.hex")
@Entity
@Table(name = "cb_organization", uniqueConstraints = {@UniqueConstraint(columnNames={"organization_id"})})
public class Organization implements Serializable
{

    …

    @OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinTable(name = "cb_organization_address",
              joinColumns = @JoinColumn(name = "organization_id"),
              inverseJoinColumns = @JoinColumn(name = "address_id"))
    /* List of addresses associated with this organization */
    private List<Address> addresses;

Notice the join table, "cb_organization_address". It's primary key is a varchar(32) not null field that I'd like to be a GUID, similar to the ID of the organization entity. How do I auto-generate an ID for this table? When I try and save an organization with addresses, I get the exception …

javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: Field 'ID' doesn't have a default value
    org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1361)
    org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1289)
    org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1295)
    org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:976)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    java.lang.reflect.Method.invoke(Method.java:597)
    org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:240)
    $Proxy47.flush(Unknown Source)
    org.mainco.subco.organization.repo.OrganizationDaoImpl.save(OrganizationDaoImpl.java:63)
    org.mainco.subco.organization.service.OrganizationServiceImpl.save(OrganizationServiceImpl.java:64)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    java.lang.reflect.Method.invoke(Method.java:597)
    org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:318)
    org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
    org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
    $Proxy62.save(Unknown Source)
    org.mainco.subco.sbadmin.controllers.OrganizationController.save(OrganizationController.java:204)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    java.lang.reflect.Method.invoke(Method.java:597)
    org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:213)
    org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:126)
        org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:96)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578)
    org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
    org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:754)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
like image 427
Dave Avatar asked Nov 12 '22 17:11

Dave


1 Answers

You should not auto-generate an ID for a join table. Instead, you should remove the ID column from cb_organization_address.

Join tables don't generally have their own IDs, they merely represent associations between two things. So the 'identity' of the relationship itself is often the compound key of the two things being related. For your use-case, I'd say that's the correct data model: each organization can have any address zero or one times, each address could be in any number of organizations.

like image 79
sharakan Avatar answered Nov 15 '22 11:11

sharakan