java Hibernate在创建表时交换列,它到底为什么要这样做?

eoigrqb6  于 7个月前  发布在  Java
关注(0)|答案(1)|浏览(78)

这是一个MRE:

package com.example.h2_demo;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.jdbc.Sql;

import java.util.List;

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;

@DataJpaTest
@ActiveProfiles("test")
@Sql(
        executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD,
        scripts = {"/create_user_table.sql", "/insert_user.sql"}
)
public class H2DemoApplicationTest {
    private final UserRepository userRepository;

    @Autowired
    public H2DemoApplicationTest(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Test
    void testNothing() {
    }

    @Test
    void getUsers() {
        List<User> users = userRepository.findAll();
        assertThat(users).asList().hasSize(1);
        User actualUser = users.get(0);
        User expectedUser = expectedUser();
        assertThat(actualUser.getId()).isEqualTo(expectedUser.getId());
        assertThat(actualUser.getName()).isEqualTo(expectedUser.getName());
        assertThat(actualUser.getLastName()).isEqualTo(expectedUser.getLastName());
    }

    private User expectedUser() {
        User expectedUser = new User();
        expectedUser.setId(1L);
        expectedUser.setName("John");
        expectedUser.setLastName("Doe");
        return expectedUser;
    }
}
package com.example.h2_demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class H2DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(H2DemoApplication.class, args);
    }
}
package com.example.h2_demo;

import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Long> {
}
package com.example.h2_demo;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Getter;
import lombok.Setter;

@Entity
@Table(name = "users")
@Setter
@Getter
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(name = "name")
    private String name;
    @Column(name = "last_name")
    private String lastName;
}
CREATE TABLE IF NOT EXISTS users(
  id INTEGER PRIMARY KEY,
  name VARCHAR(50) NOT NULL,
  last_name VARCHAR(50)
);
INSERT INTO users
VALUES (1, 'John', 'Doe');
# application-test.properties

# show SQL executed by Hibernate
spring.jpa.properties.hibernate.show_sql=true

# show meta comments in Hibernate statements (as specified by org.springframework.data.jpa.repository.Meta annotations)
spring.jpa.properties.hibernate.use_sql_comments=true

# to enable line breaks and indentation in logged queries executed by Hibernate
spring.jpa.properties.hibernate.format_sql=true

logging.level.org.hibernate.type=trace

logging.level.org.springframework.jdbc.core=TRACE

# to see what @Sql scripts are executed
logging.level.org.springframework.test.context.jdbc=DEBUG

# to see what @Sql statements are executed
logging.level.org.springframework.jdbc.datasource.init=DEBUG

测试结果:

org.opentest4j.AssertionFailedError: 
expected: "John"
 but was: "Doe"
Expected :"John"
Actual   :"Doe"


从日志中:

Hibernate: 
    drop table if exists users cascade 
Hibernate: 
    create table users (
        id bigint generated by default as identity,
        last_name varchar(255),
        name varchar(255),
        primary key (id)
    )


看到没?Hibernate打乱了列的顺序。当然,我可以禁用ddl-auto(或者在DML脚本中指定列),但我很好奇为什么Hibernate会在这么简单的任务上失败。从来没有见过这样的事情。Hibernate保证表列的创建顺序与相应实体中的字段完全相同吗?如果不是,为什么不呢?这完全超出了我的理解能力

luaexgnf

luaexgnf1#

这在official user guide中并不明显,但不,Hibernate并不能保证这一点
如果hibernate.hbm2ddl.auto配置设置为create,Hibernate将生成以下数据库模式:
示例323.自动生成的数据库模式

create table Customer (
   id integer not null,
   accountsPayableXrefId binary,
   image blob,
   name varchar(255),
   primary key (id)
)

字符串
后来在指南中…
示例335. @LazyGroup示例

@Entity public class Customer {

  @Id     private Integer id;

  private String name;

  @Basic(fetch = FetchType.LAZY)  private UUID accountsPayableXrefId;

  @Lob    @Basic(fetch = FetchType.LAZY)  @LazyGroup("lobs")  private
Blob image;

  //Getters and setters are omitted for brevity

}


注意顺序,这种不匹配意味着Hibernate会按照它认为合适的方式创建表列

相关问题