天天看点

JPA--4种主键生成策略

主键生成策略

JPA中的主键生成策略由 @GeneratedValue的strategy 属性指定:

strategy的取值有4种:

  • GenerationType.IDENTITY:自增、底层数据库必须支持自动增长方式(MySQL)
  • GenerationType.SEQUENCE:序列、底层数据库必须支持序列(Oracle)
  • GenerationType.TABLE:JPA提供的一种机制,通过一张数据库表的形式帮助我们完成主键自增
  • GenerationType.AUTO:由程序自动控制、程序自动帮我们选择主键生成策略

GenerationType.IDENTITY

package pers.zhang.domain;

import javax.persistence.*;

@Entity
@Table(name = "cst_customer")
public class Customer {

    /*
      @Id:配置主键
      @GeneratedValue:配置主键的生成策略
        strrategy:
            GenerationType.IDENTITY:自增、底层数据库必须支持自动增长方式(MySQL)
            GenerationType.SEQUENCE:序列、底层数据库必须支持序列(Oracle)
            GenerationType.TABLE:JPA提供的一种机制,通过一张数据库表的形式帮助我们完成主键自增
            GenerationType.AUTO:由程序自动控制、程序自动帮我们选择主键生成策略
      @Column:配置属性和字段的映射关系
            name:表中字段名
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "cust_id")
    private Long custId;//客户主键

    @Column(name = "cust_name")
    private String custName;//客户名称

    @Column(name = "cust_source")
    private String custSource;//客户来源

    @Column(name = "cust_industry")
    private String custIndustry;//客户所属行业

    @Column(name = "cust_level")
    private String custLevel;//客户级别

    @Column(name = "cust_address")
    private String custAddress;//客户地址

    @Column(name = "cust_phone")
    private String custPhone;//客户电话

    public Long getCustId() {
        return custId;
    }

    public void setCustId(Long custId) {
        this.custId = custId;
    }

    public String getCustName() {
        return custName;
    }

    public void setCustName(String custName) {
        this.custName = custName;
    }

    public String getCustSource() {
        return custSource;
    }

    public void setCustSource(String custSource) {
        this.custSource = custSource;
    }

    public String getCustIndustry() {
        return custIndustry;
    }

    public void setCustIndustry(String custIndustry) {
        this.custIndustry = custIndustry;
    }

    public String getCustLevel() {
        return custLevel;
    }

    public void setCustLevel(String custLevel) {
        this.custLevel = custLevel;
    }

    public String getCustAddress() {
        return custAddress;
    }

    public void setCustAddress(String custAddress) {
        this.custAddress = custAddress;
    }

    public String getCustPhone() {
        return custPhone;
    }

    public void setCustPhone(String custPhone) {
        this.custPhone = custPhone;
    }

    @Override
    public String toString() {
        return "Customer{" +
                "custId=" + custId +
                ", custName='" + custName + '\'' +
                ", custSource='" + custSource + '\'' +
                ", custIndustry='" + custIndustry + '\'' +
                ", custLevel='" + custLevel + '\'' +
                ", custAddress='" + custAddress + '\'' +
                ", custPhone='" + custPhone + '\'' +
                '}';
    }
}
           

测试:

@Test
    public void saveTest(){
        //1.加载配置文件创建工厂对象(实体管理类工厂)
        EntityManagerFactory factory = Persistence.createEntityManagerFactory("myJpa");
        //2.通过实体管理类工厂获取实体管理器
        EntityManager entityManager = factory.createEntityManager();
        //3.获取事务对象,开启事务
        EntityTransaction transaction = entityManager.getTransaction();
        transaction.begin();
        //4.进行CRUD
        Customer customer = new Customer();
        customer.setCustName("阿里巴巴");
        customer.setCustIndustry("电商");
        //保存
        entityManager.persist(customer);
        //5.提交事务或回滚事务
        transaction.commit();
        //6.释放资源
        entityManager.close();
        factory.close();

    }
           

运行JUnit测试,控制台打印:

Hibernate: drop table if exists cst_customer
Hibernate: create table cst_customer (cust_id bigint not null auto_increment, cust_address varchar(255), cust_industry varchar(255), cust_level varchar(255), cust_name varchar(255), cust_phone varchar(255), cust_source varchar(255), primary key (cust_id))
Hibernate: insert into cst_customer (cust_address, cust_industry, cust_level, cust_name, cust_phone, cust_source) values (?, ?, ?, ?, ?, ?)
           

JPA为我们自动生成了表并插入了数据:

JPA--4种主键生成策略

GenerationType.TABLE

修改strategy的值为GenerationType.TABLE

@Id
   @GeneratedValue(strategy = GenerationType.TABLE)
   @Column(name = "cust_id")
   private Long custId;//客户主键
           

运行测试方法,控制台打印:

Hibernate: drop table if exists cst_customer
Hibernate: drop table if exists hibernate_sequences
Hibernate: create table cst_customer (cust_id bigint not null, cust_address varchar(255), cust_industry varchar(255), cust_level varchar(255), cust_name varchar(255), cust_phone varchar(255), cust_source varchar(255), primary key (cust_id))
Hibernate: create table hibernate_sequences (sequence_name varchar(255) not null, next_val bigint, primary key (sequence_name))
Hibernate: select tbl.next_val from hibernate_sequences tbl where tbl.sequence_name=? for update
Hibernate: insert into hibernate_sequences (sequence_name, next_val)  values (?,?)
Hibernate: update hibernate_sequences set next_val=?  where next_val=? and sequence_name=?
Hibernate: insert into cst_customer (cust_address, cust_industry, cust_level, cust_name, cust_phone, cust_source, cust_id) values (?, ?, ?, ?, ?, ?, ?)
           

生成了cst_customer表,并插入了数据:

JPA--4种主键生成策略

于GenerationType.IDENTITY不同的是,JPA同时由生成了另一张表hibernate_sequences用与生成主键。(保存了下一次插入数据时,主键的值)

JPA--4种主键生成策略

GenerationType.SEQUENCE

应用于Oracle,根据Oracle提供的序列生成主键。

GenerationType.AUTO

与使用GenerationType.TABLE一致,生成一张表用来生成主键。

继续阅读