严格来说,应该在 basic type 的 persistent attributes 上添加 @javax.persistence.Basic 注解,但实际不需要,因为 @Basic 是默认值,因此可以省略。
JPA specification 限制只有下面类型可以被标记为 @javax.persistence.Basic
- Java primitive types and wrappers
 - java.lang.String
 - java.math.BigInteger
 - java.math.BigDecimal
 - java.util.Date
 - java.util.Calendar
 - java.sql.Date
 - java.sql.Time
 - java.sql.Timestamp
 - byte[] or Byte[]
 - char[] or Character[]
 - enums
 - any other type that implements Serializable (JPA's "support" for Serializable types is to directly serialize their state to the database).
 
即 Hibernate basic type 比 JPA 允许 @Basic 的类型多了
- java.util.Currency
 - java.util.Locale
 - java.util.TimeZone
 - java.net.URL
 - java.lang.Class
 - java.sql.Blob
 - java.sql.Clob
 - java.util.UUID
 - java.sql.NClob
 - java.time.Duration
 - java.time.Instant
 - java.time.LocalDateTime
 - java.time.LocalDate
 - java.time.LocalTime
 - java.time.OffsetDateTime
 - java.time.OffsetTime
 - java.time.ZonedDateTime
 - com.vividsolutions.jts.geom.Geometry
 - org.geolatte.geom.Geometry
 
另外 JPA 2.1 添加 javax.persistence.AttributeConverter 参见 JPA 2.1 AttributeConverters
@Basic 有两个属性
- optional - 默认 true ,表示此 attribute 是否可以是 null 。 Hibernate 使用此属性表示数据库 column 是否是 nullable
 - fetch - 默认 javax.persistence.FetchType.EAGER 。 JPA 的 EAGER 表示当 fetch Entity 时同时 fetch 此属性,另有 LAZY 表示只有当访问此属性时才 fetch 此属性。但 Hibernate 忽略 basic types 的 fetch 属性,除非使用了 bytecode enhancement
 
package org.example.demo.hibernate;
import javax.persistence.Basic;
import javax.persistence.Entity;
import javax.persistence.EntityManagerFactory;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Persistence;
public class Test {
    public static void main(String[] args) {
        EntityManagerFactory factory = Persistence.createEntityManagerFactory("test");
        factory.close();
    }
    @Entity(name = "Person")
    public static class Person {
        @Id
        @GeneratedValue
        Long id;
        @Basic(optional = false)
        String name;
    }
}
生成的 SQL
drop table if exists Person cascade
drop sequence if exists hibernate_sequence
create sequence hibernate_sequence start 1 increment 1
create table Person (id int8 not null, name varchar(255) not null, primary key (id))
如果先生成表
drop table if exists Person cascade;
drop sequence if exists hibernate_sequence;
create sequence hibernate_sequence start 1 increment 1;
create table Person (id int8 not null, name varchar(255), primary key (id));
然后修改 src/main/resources/META-INF/persistence.xml 去除 javax.persistence.schema-generation.database.action
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
             http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
  version="2.1">
  <persistence-unit name="test">
    <properties>
      <property name="javax.persistence.jdbc.url" value="jdbc:p6spy:postgresql://localhost:5432/test" />
      <property name="javax.persistence.jdbc.user" value="postgres" />
      <property name="javax.persistence.jdbc.password" value="postgres" />
    </properties>
  </persistence-unit>
</persistence>
然后执行
package org.example.demo.hibernate;
import javax.persistence.Basic;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Persistence;
public class Test {
    public static void main(String[] args) {
        EntityManagerFactory factory = Persistence.createEntityManagerFactory("test");
        EntityManager em = factory.createEntityManager();
        em.getTransaction().begin();
        em.persist(new Person());
        em.getTransaction().commit();
        em.close();
        factory.close();
    }
    @Entity(name = "Person")
    public static class Person {
        @Id
        @GeneratedValue
        Long id;
        @Basic(optional = false)
        String name;
    }
}
在 17 行依然报异常 javax.persistence.PersistenceException: org.hibernate.PropertyValueException: not-null property references a null or transient value : org.example.demo.hibernate.Test$Person.name
即 Hibernate 不管数据库是否有 not null 约束,只要 @Basic.optional = false 则会检查是否 null