前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JPA 详解

JPA 详解

作者头像
代码拾遗
发布2018-07-24 15:49:33
4.8K0
发布2018-07-24 15:49:33
举报
文章被收录于专栏:代码拾遗代码拾遗
简介

Java Persistence API(JPA)是将Java对象和关系型数据库对象映射起来规范。实现这个规范后开发者可以使用相同的代码可以在任意的数据库中执行CRUD操作,实现的框架不仅仅是处理和数据库交换的代码(JDBC),同时也会将数据库中的数据和Java对象映射起来,无需手动进行转换。此教程基于JAP2.1。 JPA 主要包含的组件:

  • 实体: 对于当前JPA的规范,实体就是POJO。
  • 对象关系信息:应用开发者必须提供数据库表数据和Java对象之间的对应关系
  • JPQL: JPA的目的是抽象具体的数据库,框架仍然提供了类SQL的方式处理特殊的方法
项目实战

首先创建项目:

代码语言:javascript
复制
mvn archetype:create -DgroupId=com.javacodegeeks.ultimate -DartifactId=jpa

添加依赖:

代码语言:javascript
复制
<properties>
    <jee.version>7.0</jee.version>
    <h2.version>1.3.176</h2.version>
    <hibernate.version>4.3.8.Final</hibernate.version>
</properties>

<dependencies>
    <dependency>
        <groupId>javax</groupId>
        <artifactId>javaee-api</artifactId>
        <version>${jee.version}</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <version>${h2.version}</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-entitymanager</artifactId>
        <version>${hibernate.version}</version>
    </dependency>
</dependencies>
EntityManager 和 Persistence Unit

配置 persistence.xml信息,文件保存在src/main/resource/META-INF下。

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
 http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">

    <persistence-unit name="PersistenceUnit" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <properties>
            <property name="connection.driver_class" value="org.h2.Driver"/>
            <property name="hibernate.connection.url" value="jdbc:h2:~/jpa"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
            <property name="hibernate.hbm2ddl.auto" value="create"/>
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>
        </properties>
    </persistence-unit>
</persistence>

事务类型设置的是RESOURCE_LOCAL,表示事务由应用自己控制,如果使用了容器提供的事务可以设置为JTA。 provider 设置为org.hibernate.ejb.HibernatePersistence 表示使用Hibernate实现的JPA。 之后的设置就是设置JPA连接数据库的基本信息。

代码语言:javascript
复制
public class Main {
    private static final Logger LOGGER = Logger.getLogger("JPA");

    public static void main(String[] args) {
        Main main = new Main();
        main.run();
    }

    public void run() {
        EntityManagerFactory factory = null;
        EntityManager entityManager = null;
        try {
            factory = Persistence.createEntityManagerFactory("PersistenceUnit");
            entityManager = factory.createEntityManager();
            persistPerson(entityManager);
        } catch (Exception e) {
            LOGGER.log(Level.SEVERE, e.getMessage(), e);
            e.printStackTrace();
        } finally {
            if (entityManager != null) {
                entityManager.close();
            }
            if (factory != null) {
                factory.close();
            }
        }
    }
    ...

JPA中所有的操作基本都由EntityManager完成。为了获取EntityManger,需要创建EntityManagerFactory实例。一个应用尽需要一个EntityManagerFactory。

事务

现在来实现上面代码的persistPersion()方法,以为我们选择的是事务类型是本地事务,所有事务要有应用控制,存储一个对象

代码语言:javascript
复制
private void persistPerson(EntityManager entityManager) {
    EntityTransaction transaction = entityManager.getTransaction();
    try {
        transaction.begin();
        Person person = new Person();
        person.setFirstName("Homer");
        person.setLastName("Simpson");
        entityManager.persist(person);
        transaction.commit();
    } catch (Exception e) {
        if (transaction.isActive()) {
            transaction.rollback();
        }
    }
}

上述的Person对象的定义:表名为T_PERSION

代码语言:javascript
复制
@Entity
@Table(name = "T_PERSON")
public class Person {
    private Long id;
    private String firstName;
    private String lastName;

    @Id
    @GeneratedValue
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Column(name = "FIRST_NAME")
    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    @Column(name = "LAST_NAME")
    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}

如果表明和类名相同,那么@Table是可以省略的,但是仍然推荐加上。 注解@Column 是用来映射Java对象和表中的列的,及时不加注解,JPA仍然会映射,除非其使用注解@Transient修饰,则不会被映射。关于@Column的使用

代码语言:javascript
复制
@Colunm(name="FIRST_NAME", length=100, nullable = false, unique = false)

上述注解的意思就是映射表中列名为FIRST_NAME的列,长度100字符,不能空,不唯一,当试图插入null值是会抛出异常并会滚事务。 对于@Id和@GeneratedValue是告诉JAP,这个值是主键并且其值是由数据库自动生成的。 上述例子,@Column是修饰getter的同样可以直接修饰字段。

代码语言:javascript
复制
@Entity
@Table(name = "T_PERSON")
public class Person {
    @Id
    @GeneratedValue
    private Long id;
    @Column(name = "FIRST_NAME")
    private String firstName;
    @Column(name = "LAST_NAME")
    private String lastName;
    ...

这两种方法几乎没什么区别,唯一的区别在于如果注解修饰字段子类无法重写其注解。 另一个需要注意的是需要在一个实体的层次上使用一种注解方式。可以在JPA的整个项目混用注解字段或者方法,但是在一个实体和它的子类中需要确保使用的是同一种注解方式。如果要修改子类的注解方式,可以使用 @Access注解改变

代码语言:javascript
复制
@Entity
@Table(name = "T_GEEK")
@Access(AccessType.PROPERTY)
public class Geek extends Person {
...
继承

对于Geek类,其直接继承与Person

代码语言:javascript
复制
@Entity
@Table(name = "T_GEEK")
public class Geek extends Person {
    private String favouriteProgrammingLanguage;
    private List<Project> projects = new ArrayList<Project>();

    @Column(name = "FAV_PROG_LANG")
    public String getFavouriteProgrammingLanguage() {
            return favouriteProgrammingLanguage;
    }

    public void setFavouriteProgrammingLanguage(String favouriteProgrammingLanguage) {
        this.favouriteProgrammingLanguage = favouriteProgrammingLanguage;
    }
    ...
}

Hibernate 会重新创建T_PERSON表

代码语言:javascript
复制
Hibernate: create table T_PERSON (DTYPE varchar(31) not null, id bigint generated by default as identity, FIRST_NAME varchar(255), LAST_NAME varchar(255), FAV_PROG_LANG varchar(255), primary key (id))

保存Geek

代码语言:javascript
复制
private void persistGeek(EntityManager entityManager) {
    EntityTransaction transaction = entityManager.getTransaction();
    transaction.begin();
    Geek geek = new Geek();
    geek.setFirstName("Gavin");
    geek.setLastName("Coffee");
    geek.setFavouriteProgrammingLanguage("Java");
    entityManager.persist(geek);
    geek = new Geek();
    geek.setFirstName("Thomas");
    geek.setLastName("Micro");
    geek.setFavouriteProgrammingLanguage("C#");
    entityManager.persist(geek);
    geek = new Geek();
    geek.setFirstName("Christian");
    geek.setLastName("Cup");
    geek.setFavouriteProgrammingLanguage("Java");
    entityManager.persist(geek);
    transaction.commit();
}

T_PERSION保存的数据

代码语言:javascript
复制
sql> select * from t_person;
DTYPE  | ID | FIRST_NAME | LAST_NAME | FAV_PROG_LANG
Person | 1  | Homer      | Simpson   | null
Geek   | 2  | Gavin      | Coffee    | Java
Geek   | 3  | Thomas     | Micro     | C#
Geek   | 4  | Christian  | Cup       | Java

DTYPE表示了不同类型的PERSON,对于Person,其FAV_PROG_LANG是null。 如果不喜欢使用字符串类型的鉴别器,可以设置@DiscriminatorColumn来表示不同的类型

代码语言:javascript
复制
@DiscriminatroColumn(name="PERSION_TYPE",discriminatorType=DiscriminatroType.INTEGER)

存储结果:

代码语言:javascript
复制
sql> select * from t_person;
PERSON_TYPE | ID | FIRST_NAME | LAST_NAME | FAV_PROG_LANG
-1907849355 | 1  | Homer      | Simpson   | null
2215460     | 2  | Gavin      | Coffee    | Java
2215460     | 3  | Thomas     | Micro     | C#
2215460     | 4  | Christian  | Cup       | Java

并不是所有情况下都想把信息存储在一张表中,可以使用@Inheritance选择不同的存储策略,对于这种一共有三种选择:

  • SINGLE_TABLE: 这个策略就是把所有的字段映射到一张表中
  • JOINERD: 对每个实体创建一张表。每个表只包含其映射的对象的信息,加载一个实体的时候,通过join的方式获取所有的信息,虽然降低了存储空间,但是
  • TABLE_PER_CLASS: 所有的表中都会包含全部信息。 使用JOIN的方式: @Inheritance(strategy=InheritanceType.JOINED) Hibernate会创建两张表: Hibernate: create table T_GEEK (FAV_PROG_LANG varchar(255), id bigint not null, primary key (id)) Hibernate: create table T_PERSON (id bigint generated by default as identity, FIRST_NAME varchar(255), LAST_NAME varchar(255), primary key (id)) 其获取值: sql> select * from t_person; ID | FIRST_NAME | LAST_NAME 1 | Homer | Simpson 2 | Gavin | Coffee 3 | Thomas | Micro 4 | Christian | Cup (4 rows, 12 ms) sql> select * from t_geek; FAV_PROG_LANG | ID Java | 2 C# | 3 Java | 4 (3 rows, 7 ms) 使用SQL获取完整的值: select person0_.id as id1_2_, person0_.FIRST_NAME as FIRST_NA2_2_, person0_.LAST_NAME as LAST_NAM3_2_, person0_1_.FAV_PROG_LANG as FAV_PROG1_1_, case when person0_1_.id is not null then 1 when person0_.id is not null then 0 end as clazz_ from T_PERSON person0_ left outer join T_GEEK person0_1_ on person0_.id=person0_1_.id 使用JPA实现如下: TypedQuery<Person> query = entityManager.createQuery("from Person", Person.class); List<Person> resultList = query.getResultList(); for (Person person : resultList) { StringBuilder sb = new StringBuilder(); sb.append(person.getFirstName()).append(" ").append(person.getLastName()); if (person instanceof Geek) { Geek geek = (Geek)person; sb.append(" ").append(geek.getFavouriteProgrammingLanguage()); } LOGGER.info(sb.toString()); } 关系 表,实体之间的关系主要有,1对1,1对多,多对多,嵌入,集合。 1对1 @Entity @Table(name = "T_ID_CARD") public class IdCard { private Long id; private String idNumber; private Date issueDate; @Id @GeneratedValue public Long getId() { return id; } public void setId(Long id) { this.id = id; } @Column(name = "ID_NUMBER") public String getIdNumber() { return idNumber; } public void setIdNumber(String idNumber) { this.idNumber = idNumber; } @Column(name = "ISSUE_DATE") @Temporal(TemporalType.TIMESTAMP) public Date getIssueDate() { return issueDate; } public void setIssueDate(Date issueDate) { this.issueDate = issueDate; } } @Temporal告诉JPA如何将其序列化保存到数据库中,可以选择DATE,TIME,TIMESTAMP 然后设置JPA,每个Persion都有一个IdCard @Entity @Table(name = "T_PERSON") public class Person { ... private IdCard idCard; ... @OneToOne @JoinColumn(name = "ID_CARD_ID") public IdCard getIdCard() { return idCard; } 创建表的语句: ```SQL create table T_ID_CARD ( id bigint generated by default as identity, ID_NUMBER varchar(255), ISSUE_DATE timestamp, primary key (id) )

create table T_PERSON ( id bigint generated by default as identity, FIRST_NAME varchar(255), LAST_NAME varchar(255), ID_CARD_ID bigint, primary key (id) )

代码语言:javascript
复制
@OneToOne有一个重要特性就是可以设置何时获取IdCard。
```Java
@OneToOne(fetch = FetchType.EAGER)

默认值EAGER表示每次获取Person都要获取IdCard

代码语言:javascript
复制
@OneToOne(fetch = FetchType.LAZY)

表示只有在需要IdCard的时候才会去获取 其获取SQL如下:

代码语言:javascript
复制
Hibernate: 
    select
        person0_.id as id1_3_,
        person0_.FIRST_NAME as FIRST_NA2_3_,
        person0_.ID_CARD_ID as ID_CARD_4_3_,
        person0_.LAST_NAME as LAST_NAM3_3_,
        person0_1_.FAV_PROG_LANG as FAV_PROG1_1_,
        case 
            when person0_1_.id is not null then 1 
            when person0_.id is not null then 0 
        end as clazz_ 
    from
        T_PERSON person0_ 
    left outer join
        T_GEEK person0_1_ 
            on person0_.id=person0_1_.id
Hibernate: 
    select
        idcard0_.id as id1_2_0_,
        idcard0_.ID_NUMBER as ID_NUMBE2_2_0_,
        idcard0_.ISSUE_DATE as ISSUE_DA3_2_0_ 
    from
        T_ID_CARD idcard0_ 
    where
        idcard0_.id=?
1对多
代码语言:javascript
复制
@Entity
@Table(name = "T_PHONE")
public class Phone {
    private Long id;
    private String number;
    private Person person;

    @Id
    @GeneratedValue
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Column(name = "NUMBER")
    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "PERSON_ID")
    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }
}

对于Person

代码语言:javascript
复制
private List<Phone> phones = new ArrayList<>();
...
@OneToMany(mappedBy = "person", fetch = FetchType.LAZY)
public List<Phone> getPhones() {
    return phones;
}

@OneToMany 的mappedBy 表示使用Phone中的person字段来关联。其fetch设置为LAZY模式,因为每次获取Person的时候不一定需要其Phone,如果需要可以通过如下方式获取:

代码语言:javascript
复制
TypedQuery<Person> query = entityManager.createQuery("from Person p left join fetch p.phones", Person.class);

对应的SQL如下:

代码语言:javascript
复制
select
    person0_.id as id1_3_0_,
    phones1_.id as id1_4_1_,
    person0_.FIRST_NAME as FIRST_NA2_3_0_,
    person0_.ID_CARD_ID as ID_CARD_4_3_0_,
    person0_.LAST_NAME as LAST_NAM3_3_0_,
    person0_1_.FAV_PROG_LANG as FAV_PROG1_1_0_,
    case 
        when person0_1_.id is not null then 1 
        when person0_.id is not null then 0 
    end as clazz_0_,
    phones1_.NUMBER as NUMBER2_4_1_,
    phones1_.PERSON_ID as PERSON_I3_4_1_,
    phones1_.PERSON_ID as PERSON_I3_3_0__,
    phones1_.id as id1_4_0__ 
from
    T_PERSON person0_ 
left outer join
    T_GEEK person0_1_ 
        on person0_.id=person0_1_.id 
left outer join
    T_PHONE phones1_ 
        on person0_.id=phones1_.PERSON_ID
多对多
代码语言:javascript
复制
@Entity
@Table(name = "T_PROJECT")
public class Project {
    private Long id;
    private String title;
    private List<Geek> geeks = new ArrayList<Geek>();

    @Id
    @GeneratedValue
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Column(name = "TITLE")
    public String getTitle() {
        return title;
    }

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

    @ManyToMany(mappedBy="projects")
    public List<Geek> getGeeks() {
        return geeks;
    }

    public void setGeeks(List<Geek> geeks) {
        this.geeks = geeks;
    }
}

通过@ManyToMany中的mappedBy得知,需要在Geek中的字段projects做多对多关系 Geek类:

代码语言:javascript
复制
private List<Project> projects = new ArrayList<>();
...
@ManyToMany
@JoinTable(
        name="T_GEEK_PROJECT",
        joinColumns={@JoinColumn(name="GEEK_ID", referencedColumnName="ID")},
        inverseJoinColumns={@JoinColumn(name="PROJECT_ID", referencedColumnName="ID")})
public List<Project> getProjects() {
    return projects;
}

在Geek类中提供了@JoinTable明确其和哪个表做join,joinColunms和inverseJoinConlumns则表示如何做JOIN。 如果是在Project中实现是同样的,只需要将joinColumns和inverseJoinColumn换一下即可 Project类

代码语言:javascript
复制
@ManyToMany
@JoinTable(
        name="T_GEEK_PROJECT",
        joinColumns={@JoinColumn(name="PROJECT_ID", referencedColumnName="ID")},
        inverseJoinColumns={@JoinColumn(name="GEEK_ID", referencedColumnName="ID")})
public List<Geek> getGeeks() {
    return geeks;
}

Geek类:

代码语言:javascript
复制
@ManyToMany(mappedBy="geeks")
public List<Project> getProjects() {
    return projects;
}

获取如下:

代码语言:javascript
复制
List<Geek> resultList = entityManager.createQuery("from Geek g where g.favouriteProgrammingLanguage = :fpl", Geek.class).setParameter("fpl", "Java").getResultList();
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
Project project = new Project();
project.setTitle("Java Project");
for (Geek geek : resultList) {
    project.getGeeks().add(geek);
    geek.getProjects().add(project);
}
entityManager.persist(project);
transaction.commit();
嵌入元素/嵌入的集合

如果想要在Java中更加细粒度的控制其model可以使用嵌入模式。例如Project有startDate 和 endDate,可以创建Period类以便重用开始和结束时间。

代码语言:javascript
复制
@Embeddable
public class Period {
    private Date startDate;
    private Date endDate;

    @Column(name ="START_DATE")
    public Date getStartDate() {
        return startDate;
    }

    public void setStartDate(Date startDate) {
        this.startDate = startDate;
    }

    @Column(name ="END_DATE")
    public Date getEndDate() {
        return endDate;
    }

    public void setEndDate(Date endDate) {
        this.endDate = endDate;
    }
}

在Project中加入:

代码语言:javascript
复制
private Period projectPeriod;

@Embedded
public Period getProjectPeriod() {
    return projectPeriod;
}

public void setProjectPeriod(Period projectPeriod) {
    this.projectPeriod = projectPeriod;
}

Project表结构:

代码语言:javascript
复制
create table T_PROJECT (
    id bigint generated by default as identity,
    END_DATE timestamp,
    START_DATE timestamp,
    projectType varchar(255),
    TITLE varchar(255),
    primary key (id)
)

查询:

代码语言:javascript
复制
entityManager.createQuery("from Project p where p.projectPeriod.startDate = :startDate", Project.class).setParameter("startDate", createDate(1, 1, 2015));
数据类型和转换

SQL类型

java类型

VARCHAR (CHAR, VARCHAR2, CLOB, TEXT)

String (char, char[])

NUMERIC (NUMBER, INT, LONG, FLOAT, DOUBLE)

Number (BigDecimal, BigInteger, Integer, Double, Long, Float, Short, Byte)

NUMERIC (NUMBER, INT, LONG, FLOAT, DOUBLE)

int, long, float, double, short, byte

VARBINARY (BINARY, BLOB)

byte[]

BOOLEAN (BIT, SMALLINT, INT, NUMBER)

boolean(Boolean)

TIMESTAMP (DATE, DATETIME)

java.util.Date, java.sql.Date, java.sql.Time, java.sql.Timestamp, java.util.Calendar

NUMERIC (VARCHAR, CHAR)

java.lang.Enum

VARBINARY (BINARY, BLOB)

java.util.Serializable

例如使用enum

代码语言:javascript
复制
@Entity
@Table(name = "T_PROJECT")
public class Project {
...
    private ProjectType projectType;

    public enum ProjectType {
        FIXED, TIME_AND_MATERIAL
    }
    ...
    @Enumerated(EnumType.ORDINAL)
    public ProjectType getProjectType() {
        return projectType;
    }

    public void setProjectType(ProjectType projectType) {
        this.projectType = projectType;
    }
}

通过使用@Enumerated 将enum和数据库的字段进行映射,EnumType.ORDINAL 表示使用数字表示enum并保存到数据中。

代码语言:javascript
复制
sql> select * from t_project;
ID | PROJECTTYPE | TITLE
1  | 1           | Java Project
(1 row, 2 ms)

如果使用 EnumType.String 则表示使用String保存,调用enum的方法name()获取其名字。

代码语言:javascript
复制
sql> select * from t_project;
ID | PROJECTTYPE       | TITLE
1  | TIME_AND_MATERIAL | Java Project
(1 row, 2 ms)

如果没有满足需要的转换器,可以自己构建

代码语言:javascript
复制
@Converter
public class BooleanConverter implements AttributeConverter<Boolean, Integer> {

    @Override
    public Integer convertToDatabaseColumn(Boolean aBoolean) {
        if (Boolean.TRUE.equals(aBoolean)) {
            return 1;
        } else {
            return -1;
        }
    }

    @Override
    public Boolean convertToEntityAttribute(Integer value) {
        if (value == null) {
            return Boolean.FALSE;
        } else {
            if (value == 1) {
                return Boolean.TRUE;
            } else {
                return Boolean.FALSE;
            }
        }
    }
}

使用

代码语言:javascript
复制
private boolean valid;
...
@Column(name = "VALID")
@Convert(converter = BooleanConverter.class)
public boolean isValid() {
    return valid;
}

public void setValid(boolean valid) {
    this.valid = valid;
}

结果如下:

代码语言:javascript
复制
sql> select * from t_id_card;
ID | ID_NUMBER | ISSUE_DATE              | VALID
1  | 4711      | 2015-02-04 16:43:30.233 | -1
标准API

目前为止一直使用JPQL来查询数据库,现在通过使用JPQL提供的标准的API来查询。 例如:

代码语言:javascript
复制
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Person> query = builder.createQuery(Person.class);
Root<Person> personRoot = query.from(Person.class);
query.where(builder.equal(personRoot.get("firstName"), "Homer"));
List<Person> resultList = entityManager.createQuery(query).getResultList();

首先通过EntityManger创建CriteriaBuilder。通过CruiteriaBuilder创建CriteriaQuery。提供一个函数获取where语句

代码语言:javascript
复制
query.where(builder.equal(personRoot.get("firstName"), "Homer"));

对于多where语句

代码语言:javascript
复制
query.where(builder.and(
    builder.equal(personRoot.get("firstName"), "Homer"), 
    builder.equal(personRoot.get("lastName"), "Simpson")));

CriteriaQuery定义了一下子句和选项:

  • distinct() 清除重复
  • from() 设置查询的表
  • select() 表示select语句
  • multiselect() select的列表
  • where() where子句
  • orderBy() 确定排序顺序
  • groupBy() 分组结果
  • having() having子句
  • subquery() 子查询
序列

对于@GeneratedValue提供了三种策略:

  • TABLE: JPA创建另一个表来提供序号
  • SEQUENCE: 如果数据库支持SEQUENCE,使用SEQUENCE方式创建序号
  • IDENTITY: 数据库提供标识列使用标识列提供序号

例如使用TABLE

代码语言:javascript
复制
@Id
@GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GENERATOR")
@TableGenerator(name = "TABLE_GENERATOR", table="T_SEQUENCES", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_VALUE", pkColumnValue = "PHONE")
public Long getId() {
    return id;
}

SQL

代码语言:javascript
复制
sql> select * from t_sequences;
SEQ_NAME | SEQ_VALUE
PHONE    | 1

使用SEQUENCE

代码语言:javascript
复制
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "S_PROJECT")
@SequenceGenerator(name = "S_PROJECT", sequenceName = "S_PROJECT", allocationSize = 100)
public Long getId() {
    return id;
}

通过@SequenceGenerator JPA获取其SEQUENCE,名字为S_PROJECT,分配的大小(100)。 使用IDENTITY

代码语言:javascript
复制
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Long getId() {
    return id;
}

表:

代码语言:javascript
复制
create table T_ID_CARD (
    id bigint generated by default as identity,
    ID_NUMBER varchar(255),
    ISSUE_DATE timestamp,
    VALID integer,
    primary key (id)
)
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-05-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 代码拾遗 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
  • 项目实战
  • EntityManager 和 Persistence Unit
  • 事务
  • 继承
    • 1对多
      • 多对多
        • 嵌入元素/嵌入的集合
        • 数据类型和转换
          • 标准API
          • 序列
          相关产品与服务
          数据库
          云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档