JPA (Java Persistence API) is a specification in Java that simplifies database interactions by mapping Java classes to relational database tables. An @Entity annotation marks a class as an entity, where each instance of the class represents a row in the table. JPA uses annotations such as @Entity, @Id and @Table to define this mapping.
We will cover three main annotations used in JPA:
- @Table
- @Entity
- @Id
@Table Annotation
The @Table annotation in JPA is used to define the database table mapping for an entity. It allows customization of:
- Table name (default is the entity class name)
- Catalog and schema (useful for multi-database environments)
- Unique constraints on specific columns
Syntax
import jakarta.persistence.*;
@Entity
@Table(name = "student") // Custom table name
public class Student {
// Fields and methods
}
Attributes of @Table Annotation
The @Table annotation provides the following attributes:
- name: Defines the table name (default: entity class name).
- catalog: Specifies the database catalog.
- schema: Defines the database schema.
- uniqueConstraints: Enforces unique constraints on specific columns
@Entity Annotation
The @Entity annotation of the Java class can indicate that it is the entity and it can represent the tables in the relational database. When a class is annotated with @Entity, JPA treats it as a persistent Java object whose state can be stored in and retrieved from a database.
Key points:
- Must be placed at the class level.
- The class should have a no-argument constructor.
- Must have a primary key field marked with @Id.
Syntax
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
@Entity
public class Student {
@Id
private int id; // Primary Key
private String name;
private String course;
// Constructors, getters, setters
}
@Id Annotation
The @Id annotation in JPA marks a field as the primary key of an entity. It uniquely identifies each row in the corresponding database table and is mandatory for every entity
Syntax
@Entity
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String department;
// Getters and setters
}
The @GeneratedValue annotation defines how primary key values are automatically generated.
Example: GenerationType.IDENTITY (auto-increment), GenerationType.SEQUENCE or GenerationType.AUTO
Step-by-Step Implementation Example
Step 1: Create a Maven project in IntelliJ IDEA
- File ->New-> Project ->Maven
- Check “Create from archetype” off (simple project)
- GroupId: org.example
ArtifactId: create-entity-demo - Language level: Java 11 (or 17)
Step 2: Verify the project structure
Once the project then the file structure looks like the image below.

Step 3: Add dependencies (pom.xml)
Use Hibernate 6, MySQL 8 and JAXB (for XML handling). Also set the compiler to Java 11
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>create-entity-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<name>create-entity-demo</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<junit.version>5.9.2</junit.version>
</properties>
<dependencies>
<!-- Hibernate Core (Jakarta) -->
<dependency>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-core</artifactId>
<version>6.0.2.Final</version>
</dependency>
<!-- MySQL JDBC Driver -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<!-- JAXB (needed for persistence.xml handling in Java 11+) -->
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>3.0.2</version>
</dependency>
<!-- JUnit 5 (optional, for tests) -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- (Optional) Surefire for tests -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M9</version>
</plugin>
</plugins>
</build>
</project>
Step 4: Create persistence.xml
Open the persistence.xml and put the below code into the project and it can configure the database of the project.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<persistence xmlns="https://jakarta.ee/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd"
version="3.0">
<persistence-unit name="example-unit">
<!-- List your entity classes -->
<class>org.example.app.entity.Product</class>
<properties>
<!-- JDBC basics -->
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/example?createDatabaseIfNotExist=true&useSSL=false&allowPublicKeyRetrieval=true"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value=""/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
<!-- Hibernate provider settings -->
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<!-- Helpful while learning -->
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.use_sql_comments" value="true"/>
</properties>
</persistence-unit>
</persistence>
Step 5: Create the Entity (@Entity, @Id, @Table)
- The Product class is a JPA entity that maps to the products table in the database.
- It represents a product with fields for id, name and price, where id is the primary key and is auto-generated.
Product.java
import jakarta.persistence.*;
@Entity
@Table(name = "products") // customize table name
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) // auto-increment PK
private Long id;
private String name;
private double price;
// JPA requires a no-arg constructor
public Product() {}
public Product(String name, double price) {
this.name = name;
this.price = price;
}
// Getters & Setters
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public double getPrice() { return price; }
public void setPrice(double price) { this.price = price; }
}
Step 6: Create MainApp class
- The MainApp class demonstrates basic JPA operations like persisting and retrieving Product entities using EntityManager.
- It inserts sample data into the database and then queries and displays all stored products.
MainApp.java:
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.Persistence;
import java.util.List;
public class MainApp {
public static void main(String[] args) {
// Step 1: Initialize EntityManagerFactory (connects to persistence unit defined in persistence.xml)
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("example-unit");
// Step 2: Create EntityManager (used to interact with database)
EntityManager entityManager = entityManagerFactory.createEntityManager();
// Step 3: Persist sample data
persistSampleData(entityManager);
// Step 4: Retrieve and display data
displaySampleData(entityManager);
// Step 5: Close resources
entityManager.close();
entityManagerFactory.close();
}
// Persisting sample Product records into the database
private static void persistSampleData(EntityManager entityManager) {
entityManager.getTransaction().begin(); // Begin transaction
// Create sample products
Product product1 = new Product();
product1.setName("Product 1");
product1.setPrice(10.99);
Product product2 = new Product();
product2.setName("Product 2");
product2.setPrice(20.99);
// Save to DB
entityManager.persist(product1);
entityManager.persist(product2);
entityManager.getTransaction().commit(); // Commit transaction
}
// Fetching and displaying product records from database
private static void displaySampleData(EntityManager entityManager) {
List<Product> products = entityManager
.createQuery("SELECT p FROM Product p", Product.class)
.getResultList();
System.out.println("Products:");
for (Product product : products) {
System.out.println(
"ID: " + product.getId() +
", Name: " + product.getName() +
", Price: " + product.getPrice()
);
}
}
}
Step 7: Run the application
In IntelliJ: Right-click MainApp-> Run.

The application starts by creating an EntityManager, persists two Product entries into the database and then retrieves and displays them. It uses JPA's transaction management and JPQL to handle database operations.
Comparison table of @Entity,@Id and @Table
Annotation | Purpose | mandatory | Common attribute |
|---|---|---|---|
@Entity | it can represent the tables in the relational database | yes | name (optional for JPQL alias) |
@Table | Specifies the table name and other table-level properties | No | name, schema, catalog, uniqueConstraints |
@Id | Marks a field as the primary key of the entity | yes | (No attributes directly; usually combined with @GeneratedValue) |