官术网_书友最值得收藏!

Entities

To activate Java persistence on a bean class, we can use the @Entity annotation, which lets us map the bean to a database table. The identifier field denoted by @Id is used to map the primary key column of the table. The mapping of a bean to a table can be done using annotations or XML, but here we will stick to using annotations. One entity instance can be considered as representing one row of a table.

XML mapping can be used to override the values defined by annotations. This can be useful for deployment-based configuration changes without changing the code.

An entity mapping structure is shown here:

The mapping defines an entity called Task, which is mapped to a table named "task_detail". While JPA would use default names based on class and member names to map it to corresponding tables and columns, there are times when you need to handle the differences. Here, we have used the @Table annotation since our class name is Task but the table name is task_detail. Similarly, if the field names are different then we could make use of the @Column annotation. An example is as follows:

@Column(name = "last_modified")
LocalDateTime lastModified;

As of JPA 2.2, we now have support for these date/time classes:

  • java.time.LocalDate
  • java.time.LocalTime
  • java.time.LocalDateTime
  • java.time.OffsetTime
  • java.time.OffsetDateTime

Prior to JPA 2.2, while there was no support for the date/time APIs, we could have still managed the conversion of LocalDate or LocalDateTime using an AttributeConverter, as shown here, which is applied automatically to all entities having such fields due to autoApply=true:

 @Converter(autoApply = true)
public class LocalDateConverter
implements AttributeConverter<LocalDate, Date> {
@Override
public Date convertToDatabaseColumn(LocalDate entityDate) {
return (entityDate == null ? null : Date.valueOf(entityDate));
}

@Override
public LocalDate convertToEntityAttribute(Date dbDate) {
return (dbDate == null ? null : dbDate.toLocalDate());
}
}

It's now also possible to inject a bean within an AttributeConverter instance; this can be useful to fetch a configuration object which may hold the needed format or other useful information. Consider using a converter when you need to map the database representation of a value to a Java representation that can't be mapped by default.

A few common use cases could be:

  • Mapping a number value such as one or zero to a Boolean field
  • Encryption of password for saving and decryption during fetch
  • Mapping a value to a corresponding enum type

When defining the entities, it's also common to put named queries in the entity itself, which can later be referenced when querying the database using EntityManager. An example is shown here:

@Entity
@Table(name="task_detail")
@NamedQuery(name = "Task.findById",
query =
"SELECT t FROM Task t WHERE t.id = :id")
@NamedQuery(name = "Task.findByName",
query =
"SELECT t FROM Task t WHERE t.name = :name")
public class Task {
// code omitted
}

This can then be referenced during querying:

TypedQuery<Task> query = em.createNamedQuery("Task.findById", Task.class);
query.setParameter("id", 1);

//With TypedQuery you don't need a cast to Task type below
query.getSingleResult().getName();

When mapping an entity to a table, it's best to use the @Table annotation, rather than changing the Entity name itself. The reasons are:

@Entity(name="tasks") class Task { ... }
em.createQuery("SELECT t FROM Task t"); // won't work
em.createQuery("SELECT t FROM tasks t"); // is correct, since we changed the entity name

You may have noticed that we didn't use the NamedQueries container annotation. Well, JPA 2.2 makes use of repeatable annotations; this means you can leave out the superfluous container annotation and just repeat the one you need, such as NamedQuery. In the previous versions, you needed to use a container annotation such as NamedQueries which would then wrap multiple NamedQuery annotations. But that's no longer needed since JPA 2.2 takes advantage of the repeatable annotation feature introduced in Java 8:

Most annotation are repeatable, such as:

  • NamedStoredProcedureQuery
  • NamedNativeQuery
  • NamedEntityGraph
  • AttributeOverride
  • PersistenceContext

It's fairly common to see fields such as created, last_modified in most if not all tables in a database. When mapping such tables to entities, we can use a super class with the annotation @MappedSuperclass and define the common mapping fields and associations, which all subclasses inherit. The super class itself is not persisted and only used for field inheritance. Here's an example of that:

@MappedSuperclass
public class MappedSuperEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
protected Long id;

@NotNull
@Size(min = 1, max = 4000)
@Column(name = "name")
protected String name;

@NotNull
@Column(name = "created")
protected LocalDateTime created;

@Column(name = "last_modified")
protected LocalDateTime lastModified;
// code omitted
}

A subclass can override the basic mappings by using the AttributeOverride annotation. Notice we have used annotations such as @Size to put further validation constraints on our bean. These are from the Bean Validation API that we looked at earlier.

When working with multiple entities, you may need to define a relationship between them. In JPA, this is done by using annotations which support bidirectional and unidirectional relations. The following four annotations can be applied on relational members of a class:

  • @ManyToMany
  • @ManyToOne
  • @OneToMany
  • @OneToOne

It's no surprise that a table in a relational database is not designed with object-oriented thinking. Often, when mapping a entity to an table, we may want to group certain fields/members and use a composition rather than declaring all the fields in a single class. JPA provides @Embeddable to do just that.

Here's an example showing how we create a user entity with a has-a credential. The database has all the fields present in a single table:

We have covered three major types of classes that you would typically create when working with JPA:

  • Entity: This is the basic unit of bean which is used for persistence
  • MappedSuperclass: Class without its own table, but used for common field inheritance by entities
  • Embeddable: Class without its own table, properties of which can be persisted via embedding it in another entity
主站蜘蛛池模板: 南江县| 临猗县| 龙口市| 栾川县| 进贤县| 简阳市| 綦江县| 祁连县| 舒兰市| 桑植县| 延长县| 克拉玛依市| 墨江| 衡南县| 葫芦岛市| 东方市| 镇康县| 平阳县| 固原市| 鄂温| 贺州市| 新龙县| 曲沃县| 丹寨县| 长乐市| 克拉玛依市| 余干县| 屯门区| 潢川县| 湾仔区| 汽车| 弥勒县| 屏东县| 全南县| 田林县| 察雅县| 武乡县| 武陟县| 攀枝花市| 古交市| 金平|