在SpringBoot 2.1.5.RELEASE和MySQL 8.0.15中未生成GenerationType.IDENTITY

时间:2019-05-16 09:32:44

标签: hibernate spring-boot jpa junit spring-data-jpa

我有一个基本的SpringBoot 2.1.5.RELEASE应用程序。使用Spring Initializer,JPA,嵌入式Tomcat,Thymeleaf模板引擎并将其打包为可执行JAR文件。

我有这个域类:

     @Entity
        @Table(name="t_purchase")
        @JsonInclude(JsonInclude.Include.NON_NULL)
        public class Purchase implements Serializable {

            public Purchase() {
            }

            public Purchase(Shop shop) {
                super();
                this.shop = shop;
            }

            @Id
            @GeneratedValue(strategy = GenerationType.IDENTITY)
            @JsonProperty("id")
            private Long id;    

@JsonProperty("txHash")
    private String txHash;

            @ManyToOne(fetch = FetchType.EAGER)
            @JoinColumn(name = “shop_id")
            @JsonIgnore
            Shop shop;


    @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Purchase purchase = (Purchase) o;

            if (getTxHash()==null && purchase.getTxHash()==null) {
                 return id == purchase.id;
            } else {
                return Objects.equals(getTxHash(), purchase.getTxHash());
            }
        }



        @Override
        public int hashCode() {
            int result = (int) (id ^ (id >>> 32));
            result = 31 * result + Objects.hash(getTxHash());
            return result;
        }

        …
        }

然后我创建了这个Junit方法:

   @Test
    public void testFindByShopIdWithPurchases () {

        Shop shop = new Shop ("Shop_NAME");

        shopService.save(shop);

        Purchase purchase1 = new Purchase(shop);
        Purchase purchase2 = new Purchase(shop);

        shop.getPurchases().add(purchase1);
        shop.getPurchases().add(purchase2);

        shopService.save(shop);

        assertNotEquals (purchase1, purchase2);


    }   

但是我有一个AssertionError,因为似乎两个对象的ID均为0:

java.lang.AssertionError: Values should be different. Actual: Purchase [id=0, txHash=null, shop=957]

这是商店:

 @Entity
    @Table(name = “t_shop")
    public class Shop implements Serializable {


        public Shop(String name) {
            this.name = name;
        }

        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @JsonProperty("id")
        private Long id;

        @JsonProperty("name")
        private String name;

        @OneToMany(mappedBy = “shop", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
        @JsonIgnore
        private Set<Purchase> purchases = new HashSet<Purchase>();

            …
    }

4 个答案:

答案 0 :(得分:0)

将类型更改为AUTO可以为我解决问题

答案 1 :(得分:0)

 @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @JsonProperty("id")
        private Long id;   

在使用GenerationType IDENTITY 时,这意味着您应负责生成ID(如果处于休眠状态)。

如果您希望应用程序自动管理ID生成,请使用GenerationType 自动 因此,请在购买商店实体

中更新您的GenerationType
 @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        @JsonProperty("id")
        private Long id;  

............................................... ............................

如果在进行上述更改后仍然出现错误:

 java.sql.SQLSyntaxErrorException: Table 'shops_db.hibernate_sequence' doesn't exist 

默认情况下,Hibernate从hibernate_sequence表生成密钥,我们可以通过将此hibernate.use-new-id-generator-mappings设置为false来禁用它。

spring.jpa.hibernate.use-new-id-generator-mappings=false

在您的application.properties中设置此属性

答案 2 :(得分:0)

尝试更改下面提到的属性
spring.jpa.hibernate.use-new-id-generator-mappings = false 由于新的春季启动版本2.XX已将此属性更改为
spring.jpa.hibernate.use-new-id-generator-mappings = true 使用下面的链接进行详细了解
Table 'DBNAME.hibernate_sequence' doesn't exist

答案 3 :(得分:0)

从Spring 2.X.X RELEASE,spring-data-jpa模块开始,使用Hibernate5版本。如果您浏览org.springframework.data:spring-data-jpa:2.1.5.RELEASE pom.xml文件,则会发现休眠依赖的版本为

<hibernate>5.2.17.Final</hibernate>

Hibernate5 @GeneratedValue(strategy = GenerationType.IDENTITY)之前的Hibernate版本的工作原理很吸引人。但是在Hibernate5中发布以下fix是必要的。

在此处复制我的answer以供后代使用。

@Id
@GeneratedValue(strategy= GenerationType.AUTO,generator="native")
@GenericGenerator(name = "native",strategy = "native")
private Long id;

DDL

`id` BIGINT(20) NOT NULL AUTO_INCREMENT PRIMARY KEY

原因

摘录自hibernate-issue

当前,如果hibernate.id.new_generator_mappings设置为false, @GeneratedValue(strategy = GenerationType.AUTO)映射到本机。 如果此属性为true(这是5.x中的defult值),则 @GeneratedValue(strategy = GenerationType.AUTO)始终映射到 SequenceStyleGenerator。

因此,在任何不支持序列的数据库上 本机(例如MySQL),我们将改为使用TABLE生成器 身份。

但是,TABLE生成器虽然更便于移植,但却使用了单独的 每次从数据库中获取值时进行事务处理。在 实际上,即使IDENTITY禁用了JDBC批处理更新和TABLE, 生成器使用池优化器,IDENTITY的伸缩性仍然更好。