How to autoincrement an Id in a composite primary key in Hibernate?

谁说胖子不能爱 提交于 2020-12-09 09:54:15

问题


I have a table with a composite primary key - groupId and batchId. Entity class looks like:

@Entity(name="EMPLOYEE")
public class Employee {

    @EmbeddedId
    private EmployeePK employeePK;

    //Other columns and their getters and setters
    //Getters and setters
}

Composite PK:

@Embeddable
public class EmployeePK implements Serializable {

    private long groupId;
    private long batchId;

    @GeneratedValue(strategy=GenerationType.AUTO)
    public long getBatchId() {
        return batchId;
    }

    public void setBatchId(long batchId) {
        this.batchId = batchId;
    }
}

I'm trying to auto increment the batch Id, for a new record to be inserted.

//For saving
Employee employee = new Employee();
EmployeePK pk = new IRAmendmentBatchesPK();
pk.setBatchId(0);
pk.setGroupId(4388);

Employee employee = employeeRepository.save(employee);


//Repository Interface
public interface EmployeeRepository extends JpaRepository<Employee, EmployeePK>{

}

I'm explicity setting batchId as 0, in hopes that the auto-incremented value is set in the batchId during save(insert). As of now, this code will save a new entry with batchId as 0.


回答1:


As I have mentioned in comment, I have used @IdClass it worked while I have tried in hsqldb in-memory database, but failed to work in mysql.

Please note I am using hibernate 5

You may give a try with oracle, I couldn't recollect but it should work. But please check for if any drawbacks with the approach if any.

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.techdisqus</groupId>
    <artifactId>spring5-mvc-hibernate-example</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <properties>
        <failOnMissingWebXml>false</failOnMissingWebXml>
        <spring.version>5.0.0.RELEASE</spring.version>
        <hibernate.version>5.2.11.Final</hibernate.version>
        <hibernate.validator>5.4.1.Final</hibernate.validator>
        <c3p0.version>0.9.5.2</c3p0.version>
        <jstl.version>1.2.1</jstl.version>
        <tld.version>1.1.2</tld.version>
        <servlets.version>3.1.0</servlets.version>
        <jsp.version>2.3.1</jsp.version>
        <hsqldb.version>1.8.0.10</hsqldb.version>
    </properties>
    <dependencies>
        <!-- Spring MVC Dependency -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!-- Spring ORM -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!-- Hibernate ORM -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${hibernate.version}</version>
        </dependency>

        <!-- Hibernate-C3P0 Integration -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-c3p0</artifactId>
            <version>${hibernate.version}</version>
        </dependency>

        <!-- c3p0 -->
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>${c3p0.version}</version>
        </dependency>

        <!-- Hibernate Validator -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>${hibernate.validator}</version>
        </dependency>

        <!-- JSTL Dependency -->
        <dependency>
            <groupId>javax.servlet.jsp.jstl</groupId>
            <artifactId>javax.servlet.jsp.jstl-api</artifactId>
            <version>${jstl.version}</version>
        </dependency>

        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>${tld.version}</version>
        </dependency>

        <!-- Servlet Dependency -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>${servlets.version}</version>
            <scope>provided</scope>
        </dependency>

        <!-- JSP Dependency -->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>${jsp.version}</version>
            <scope>provided</scope>
        </dependency>

        <!-- HSQL Dependency -->
          <dependency>
            <groupId>hsqldb</groupId>
            <artifactId>hsqldb</artifactId>
            <version>${hsqldb.version}</version>
        </dependency>  

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.12</version>
        </dependency>
    </dependencies>

    <build>
        <sourceDirectory>src/main/java</sourceDirectory>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>

            <!-- Embedded Apache Tomcat required for testing war -->
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <path>/</path>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Book.java

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.Table;

@Entity(name = "Book")
@Table(name = "book")
@IdClass( PK.class )
public class Book {

    @Id
    @Column(name = "registration_number")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long registrationNumber;

    @Id
    @Column(name = "publisher_id")
    private Integer publisherId;

    private String title;

    public Long getRegistrationNumber() {
        return registrationNumber;
    }

    public void setRegistrationNumber(Long registrationNumber) {
        this.registrationNumber = registrationNumber;
    }

    public Integer getPublisherId() {
        return publisherId;
    }

    public void setPublisherId(Integer publisherId) {
        this.publisherId = publisherId;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    @Override
    public String toString() {
        return "Book [registrationNumber=" + registrationNumber + ", publisherId=" + publisherId + ", title=" + title
                + "]";
    }
 }

PK.java

import java.io.Serializable;
import java.util.Objects;

public class PK implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 2371758145387850080L;

    private Long registrationNumber;
    private Integer publisherId;

    public PK(Long registrationNumber, Integer publisherId) {
        this.registrationNumber = registrationNumber;
        this.publisherId = publisherId;
    }


    public PK() {
    }

    @Override
    public boolean equals(Object o) {
        if ( this == o ) {
            return true;
        }
        if ( o == null || getClass() != o.getClass() ) {
            return false;
        }
        PK pk = (PK) o;
        return Objects.equals( registrationNumber, pk.registrationNumber ) &&
                Objects.equals( publisherId, pk.publisherId );
    }

    @Override
    public int hashCode() {
        return Objects.hash( registrationNumber, publisherId );
    }
}

hibernate.cfg.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="hibernate.archive.autodetection">class,hbm</property>
        <property name="hibernate.dialect">org.hibernate.dialect.HSQLDialect</property>
        <property name="hibernate.show_sql">true</property>
        <property name="hibernate.connection.driver_class">org.hsqldb.jdbcDriver</property>
        <property name="hibernate.connection.username">sa</property>
        <property name="hibernate.connection.password"></property>
        <property name="hibernate.connection.url">jdbc:hsqldb:mem:test</property>
        <property name="hibernate.hbm2ddl.auto">create</property>

        <property name="hibernate.c3p0.min_size">5</property>
        <property name="hibernate.c3p0.max_size">20</property>
        <property name="hibernate.c3p0.acquire_increment">2</property>
        <property name="hibernate.c3p0.acquire_increment">1800</property>
        <property name="hibernate.c3p0.max_statements">150</property>
    </session-factory>
</hibernate-configuration>

HibernateConfig.java

@Configuration
@EnableTransactionManagement
@ComponentScans(value = { @ComponentScan("com.techdisqus")})
public class HibernateConfig {

    @Autowired
    private ApplicationContext context;

    @Bean
    public LocalSessionFactoryBean getSessionFactory() {
        LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean();
        factoryBean.setConfigLocation(context.getResource("classpath:hibernate.cfg.xml"));
        factoryBean.setAnnotatedClasses(Book.class);
        return factoryBean;
    }

    @Bean
    public HibernateTransactionManager getTransactionManager() {
        HibernateTransactionManager transactionManager = new HibernateTransactionManager();
        transactionManager.setSessionFactory(getSessionFactory().getObject());
        return transactionManager;
    }

}

BookDAOImpl.java

@Repository
public class BookDAOImpl implements BookDAO {

    @Autowired
    private SessionFactory sessionFactory;

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }




    public void save(Book book) {
        Session session = this.sessionFactory.openSession();
        Transaction tx = session.beginTransaction();
        session.persist(book);
        tx.commit();
        session.close();

    }

}

client code:

public class SpringHibernateMain2 {

    public static void main(String[] args) {

        ApplicationContext appContext = new AnnotationConfigApplicationContext(HibernateConfig.class);

        BookDAO personDAO = appContext.getBean(BookDAO.class);

        Book book = new Book();
        book.setPublisherId(12);
        book.setTitle("t 1");
        //book.setRegistrationNumber(2l);
        personDAO.save(book);

        System.out.println("book::"+book);




        //context.close();

    }

}

from logs while using with H:

Hibernate: call next value for hibernate_sequence Hibernate: insert into book (title, publisher_id, registration_number) values (?, ?, ?) book::Book [registrationNumber=1, publisherId=12, title=t 1]

The below is the error I get while I try with MySql

Hibernate: select next_val as id_val from hibernate_sequence for update Dec 04, 2018 6:24:53 PM org.hibernate.id.enhanced.TableStructure$1$1 execute ERROR: could not read a hi value java.sql.SQLSyntaxErrorException: Table 'security.hibernate_sequence' doesn't exist

I have tried with accepted answer in the post Hibernate insert failing when embedded key contains identity column on SQL Server but no luck with it.




回答2:


@Embeddable
public class EmployeePK implements Serializable {

    private long groupId;
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long batchId;

   
    public long getBatchId() {
        return batchId;
    }

    public void setBatchId(long batchId) {
        this.batchId = batchId;
    }

//implements equals and hashcode

}


来源:https://stackoverflow.com/questions/53595226/how-to-autoincrement-an-id-in-a-composite-primary-key-in-hibernate

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!