Как автоматически увеличить идентификатор в составном первичном ключе в Hibernate?

У меня есть таблица с составным первичным ключом - groupId и batchId. Класс сущности выглядит так:

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

    @EmbeddedId
    private EmployeePK employeePK;

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

Композитный ПК:

@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;
    }
}

Я пытаюсь автоматически увеличить идентификатор пакета для вставки новой записи.

//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>{

}

Я явно устанавливаю batchId как 0 в надежде, что автоматически увеличивающееся значение будет установлено в batchId во время сохранения (вставки). На данный момент этот код сохранит новую запись с batchId как 0.

Похоже, спящий режим не поддерживает .. forum.hibernate.org/viewtopic.php?f=1&t=1006818 .. какая версия спящего режима?

Shiva 03.12.2018 15:18

Да и вручную id ставить не стоит ..

Shiva 03.12.2018 15:19

@secretsuperstar Итак, могу ли я добиться этого?

Ramdas Nair 04.12.2018 06:35

У меня есть рабочее решение, использующее @IdClass, но оно использует h2 в базе данных памяти, но не выглядит работающим с mysql DB. Я могу опубликовать здесь, если хотите, можете попробовать оральный. Я использую hibernate 5 и spring 5. Я думаю, что spring не имеет значения.

Shiva 04.12.2018 06:42

Тот же вопрос здесь: stackoverflow.com/questions/46035660/… .. снова кажется с базой данных

Shiva 04.12.2018 06:44

@secretsuperstar Я использую Oracle, не могли бы вы разместить здесь свое решение?

Ramdas Nair 04.12.2018 10:10

Написал ответ

Shiva 04.12.2018 14:02
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
7
7
3 685
2

Ответы 2

Как я уже упоминал в комментарии, я использовал @IdClass, он работал, пока я пытался в базе данных hsqldb в памяти, но не работал в mysql.

Обратите внимание, я использую спящий режим 5

Вы можете попробовать оракул, я не мог вспомнить, но он должен работать. Но, пожалуйста, проверьте, нет ли у этого подхода недостатков.

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();

    }

}

код клиента:

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();

    }

}

из журналов при использовании с 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]

Ниже показан error, который я получаю, когда пытаюсь использовать 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

Я попытался дать принятый ответ в сообщении Ошибка вставки гибернации, когда встроенный ключ содержит столбец идентификатора на SQL Server но не повезло.

Похоже, это тоже не работает для Oracle. Оцените ответ.

Ramdas Nair 05.12.2018 08:58

в чем ошибка? вы можете попробовать генератор последовательностей (в mysql есть последовательности, поэтому их нельзя использовать)? какая версия гибернации?

Shiva 05.12.2018 09:00

Я получаю сообщение об ошибке: hibernate_sequence не существует. Версия гибернации - 5.0.12.

Ramdas Nair 05.12.2018 09:37

вы можете попробовать использовать генератор последовательности. текущий код использует AUTO. посмотрите Book.java

Shiva 05.12.2018 09:38
@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

}

Другие вопросы по теме