Data Source integration with Quarkus

Rohan Aggarwal
3 min readJul 4, 2020

--

In the last blog, we looked at what is Quarkus. How it works internally. and ways to create a quarkus project. If you have not read that blog yet I will highly recommend you do that first.

Understanding the power of Quarkus

In this blog, we will see how we can integrate PostgreSQL with Quarkus and will create a CRUD application.

So let's start with the dependencies

Dependencies

        <dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-orm-panache</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jdbc-postgresql</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-validator</artifactId>
</dependency>

These are the 3 dependencies we require for our database connection and validation.

Configuration

We need to provide the database name, driver name, username, and password. We can provide this information in the application.properties file.

#quarkus.datasource.url=jdbc:postgresql:employee_db
quarkus.datasource.driver=org.postgresql.Driver
quarkus.datasource.username=quarkus
quarkus.datasource.password=quarkus

This is the basic and the minimal information we have to provide to connect our application to a database.

Panache

Hibernate ORM is the de facto JPA implementation and offers you the full breadth of an Object Relational Mapper. It makes complex mappings possible, but it does not make simple and common mappings trivial. Hibernate ORM with Panache focuses on making your entities trivial and fun to write in Quarkus.

we can use Panache in 2 ways

  • PanacheEntity
  • PanancheRepository

PanacheEntity

In this, we define all the database queries in the entity itself. We have to extend the PanacheEntity.

@Entity
public class Employee extends PanacheEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
@NotBlank
private String firstName;
private String lastName;
private int age;
private int salary;
public Employee findById(int id) {
return findById(id);
}
public static void deleteById(int id) {
deleteById(id);
}
public static void deleteByFirstname(String name) {
delete("firstName", name);
}
public static void persist(Employee employee) {
persist(employee);
}
public static void update(Employee employee) {
update(employee);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
}

Here we are using some Panache methods like findById, deleteById, persist, delete, update, etc.

In PanacheEntity we can use javax validations like @NotNull, @Size, @NotBlank, etc.javax

We can create our custom query as well in PanacheEntity


list("age", 25); // JPQL
list("age = ?1 and firstName like ?2", 25, "%"+word+"%");
find("age = ?1 and firstName like ?2", 25, "%"+word+"%")
.page(pageIndex, 3).list();

Here we are seeing different ways to write a JPQL query. We can use ‘and’ ‘or’ in our queries. we can use LIKE, alias, etc in our queries.

Calling from Resource class

So from our controller, we can directly call entity methods.

We can call predefined methods like listAll()

@GET
public List<Employee> getAll() {
return Employee.listAll(Sort.by("firstName"));
}article

listAll() method is not defined in our employee class but if is provided by Panache entity.

    @DELETE
@Path("/{id}")
@Produces(MediaType.TEXT_PLAIN)
@Transactional
public ResponseEntity delete(@PathParam("id")int id) {
Employee.deleteById(id);
return new ResponseEntity(HttpStatus.NO_CONTENT);
}

Here we are calling the static method which we created in our Employee class. If you notice we add a new annotation @Transactional. It's mandatory to add this to make it a transactional. So that if something went wrong, it can rollback.

Panache Repository

The panache repository is almost the same as the Panache Entity. Here we are just segregating the database repository class from the entity. If we consider about Single responsibility principle then the Panache repository is a better way of executing Panache than the entity.

We have to implement PanacheRepository

@ApplicationScoped
public class EmployeeRepository implements PanacheRepository<Employee> {
public Employee findById(int id) {
return findById(id);
}
public void deleteById(int id) {
deleteById(id);
}
public void deleteByFirstname(String name) {
delete("firstName", name);
}
public void persist(Employee employee) {
persist(employee);
}
public void update(Employee employee) {
update(employee);
}
}

We can compare this with JPArepository as well.

If you want to learn more about all the predefined methods present in Panache then you can refer to the official documentation

https://quarkus.io/guides/hibernate-orm-panache

In the next blog, we will look at how to deploy Quarkus application in multiple containers.

--

--

Rohan Aggarwal