Understanding JPA, 5

本文探讨了Java持久化API (JPA) 中的单表继承策略。通过具体案例,介绍了如何利用@Inheritance、@DiscriminatorColumn等注解实现不同类型的客户在单一数据库表中的存储与区分。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Page 5 of 6

The power of inheritance

An entity can extend the following:

  • Another entity -- either concrete or abstract.
  • Another non-entity, supplying behavior or non-persistence state. The attributes you inherit from a non-entity are not persisted.
  • Mapped superclasses, supplying common entity state. Tables in a database have similar fields, but tables are not related to each other.

Let's have a look into the various types of inheritance JPA offers. For this scenario, assume that there are two types of customer: a normal customer who buys products from a physical store and an online customer who buys products over the Internet.

Single-table inheritance

In single-table inheritance, all the entities in the hierarchy are stored in a single table. Single-table inheritance is the default strategy. Thus, you could omit the @Inheritance annotation in the example code in Listing 12 and get the same result.

In the example application, both ordinary and online customers are stored in the CUSTOMER table, as shown in Table 2.

Table 2. Single-table inheritance mapping strategy
ENTITYTABLE NAME
CustomerCUSTOMER
OnlineCustomerCUSTOMER

The Customer entity has custId, firstName, lastName, custType, and address information, whereas the OnlineCustomer entity has only a website attribute and otherwise extends all features of Customer. This strategy should be reflected in the superclass, as in Listing 12.

Listing 12. A sample superclass in single-table inheritance
@Entity(name = "CUSTOMER") 
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="CUST_TYPE", discriminatorType=DiscriminatorType.STRING,length=10)
@DiscriminatorValue("RETAIL")
public class Customer implements Serializable{
@Id
@Column(name = "CUST_ID", nullable = false)
@GeneratedValue(strategy = GenerationType.AUTO)
private long custId;

@Column(name = "FIRST_NAME", nullable = false,length = 50)
private String firstName;

@Column(name = "LAST_NAME", length = 50)
private String lastName;

@Embedded
private Address address = new Address();

@Column(name = "CUST_TYPE", length = 10)
private String custType;
................
}

For the time being, ignore the DiscriminatorColumn and DiscriminatorValue annotations; you'll see how those work later. The OnlineCustomer entity will be a normal entity class that extends Customer class, as shown in Listing 13.

Listing 13. A sample subclass in single-table inheritance
@Entity(name = "ONLINECUSTOMER") //Name of the entity
@DiscriminatorValue("ONLINE")
public class OnlineCustomer extends Customer{
@Column(name = "WEBSITE", length = 100)
private String website;
............
}

Now you must create a Customer object and an OnlineCustomer object and persist them, as in Listing 14.

Listing 14. Persisting objects in single-table inheritance
......................
userTransaction.begin();
//inserting Customer
Customer customer = new Customer();
customer.setFirstName("Charles");
customer.setLastName("Dickens");
customer.setCustType("RETAIL");
customer.getAddress().setStreet("10 Downing Street");
customer.getAddress().setAppt("1");
customer.getAddress().setCity("NewYork");
customer.getAddress().setZipCode("12345");
em.persist(customer);
//Inserting Online customer
OnlineCustomer onlineCust = new OnlineCustomer();
onlineCust.setFirstName("Henry");
onlineCust.setLastName("Ho");
onlineCust.setCustType("ONLINE");
onlineCust.getAddress().setStreet("1 Mission Street");
onlineCust.getAddress().setAppt("111");
onlineCust.getAddress().setCity("NewYork");
onlineCust.getAddress().setZipCode("23456");
onlineCust.setWebsite("www.amazon.com");
em.persist(onlineCust);
userTransaction.commit();
......................

If you have a look into the CUSTOMER table now, you will find two records. The query in Listing 15 should return you the list of online customers from the data store.

Listing 15. Fetching only the subclass in single-table inheritance
..............
Query query = em.createQuery("SELECT customer FROM ONLINECUSTOMER customer");
List<OnlineCustomer> list= query.getResultList();
.................

If the CUSTOMER table stores both the Customer and the OnlineCustomer data, how will JPA distinguish one from the other? How will it fetch only the online customers? In fact, JPA cannot do this unless you provide it with a hint. That's the significance of the @DiscriminatorColumn. It tells the CUSTOMER table which column distinguishes a CUSTOMER from an ONLINE CUSTOMER. @DiscriminatorValue indicates what value identifies a CUSTOMER and an ONLINE CUSTOMER. The @DiscriminatorValue annotation needs to be provided in the superclass as well as in all the subclasses.

When you want to fetch online customers, JPA silently queries the data store as in Listing 16.

Listing 16. Distinguishing objects stored in a single table
SELECT t0.CUST_ID, t0.CUST_TYPE, t0.LAST_UPDATED_TIME, t0.APPT, t0.city, t0.street, t0.ZIP_CODE, t0.FIRST_NAME, t0.LAST_NAME, t0.WEBSITE FROM CUSTOMER t0 
WHERE t0.CUST_TYPE = 'ONLINE'

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值