Building a Java application with Hibernate and MySQL in NetBeans

NetBeans provides a practical route from a Maven project to a persistent desktop application. This walkthrough builds a small booking system with Hibernate ORM, MySQL, and Swing, while keeping persistence logic separate from the interface.

The example suits Australian sole traders and community organisations that prefer a self-hosted application over an overseas subscription. It stores customer details, Australian-dollar prices, and appointment times, and can later be adapted to a REST or Jakarta Faces front end.

Several local realities shape the design. Developers work across Sydney, Melbourne, Brisbane, and Perth; appointment times must respect daylight saving; prices need clear GST treatment; and covered organisations must consider the Privacy Act 1988.

Prepare NetBeans and the Java toolchain

Install NetBeans with Java support and a current JDK 21 LTS release. Confirm that Maven runs from the IDE, create a dedicated workspace, and set the source encoding to UTF-8.

Keep the independent NetBeans Blog articles nearby for platform notes and configuration examples. They are useful when an IDE update changes generated files, module paths, or Java support.

Create a run configuration early. It should read database settings from environment variables or protected local properties, never from values committed to the repository.

Create the MySQL database

MySQL 8.4 LTS is a sensible local baseline. After installing MySQL Community Server, connect with a maintenance account and create a UTF-8 database plus a dedicated application account.

CREATE DATABASE local_bookings
  CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
CREATE USER 'booking_app'@'localhost' IDENTIFIED BY 'replace-me';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, INDEX, REFERENCES
  ON local_bookings.* TO 'booking_app'@'localhost';

Give the account only the privileges required by the schema strategy. A prototype may need local DDL and DML rights so Hibernate can create tables; production should use validated migrations and separate deployment credentials.

Keep MySQL bound to localhost during development, enable TLS for a hosted server, and schedule encrypted backups. Test a restore before relying on the data.

Start the Maven application

In NetBeans, choose New Project, Java with Maven, then Java Application. Name the package with an Australian-oriented example domain, add a main class, and set Java 21 as the project release.

Add Hibernate and the MySQL JDBC driver through the Maven dependency window or project POM. These pins are compatible examples; use current patched versions approved by your team.

<dependency>
    <groupId>org.hibernate.orm</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>6.6.13.Final</version>
</dependency>
<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <version>9.2.0</version>
</dependency>

NetBeans can refresh dependencies and resolve them without manual downloads. If the installation also supports internal tooling, a custom tree-view node demonstrates how to expose project-specific actions in the Projects view.

Map entities with Hibernate

Start with a Booking entity rather than a database-shaped Customer record. A booking can hold customer, service, start instant, status, and price, which reduces duplication and supports multiple appointments.

@Entity
public class Booking {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String customerName;
    private String email;
    private String service;
    private String status;
    private Instant startsAt;
    private BigDecimal total;
}

Use BigDecimal for money and Instant for the appointment timestamp. Store the instant in UTC, then convert it with Australia/Sydney, Australia/Brisbane, or Australia/Adelaide for display. Sydney and Melbourne change between AEST and AEDT, Brisbane stays on AEST, and Adelaide's half-hour offset is a useful test case.

Add Hibernate Validator and a Jakarta Expression Language implementation if using bean validation. Configure the Jakarta Persistence unit in META-INF/persistence.xml; this minimal property set establishes the driver and connection:

<property name="jakarta.persistence.jdbc.driver"
          value="com.mysql.cj.jdbc.Driver"/>
<property name="jakarta.persistence.jdbc.url"
          value="jdbc:mysql://localhost:3306/local_bookings?serverTimezone=UTC"/>
<property name="jakarta.persistence.jdbc.user" value="${DB_USER}"/>
<property name="jakarta.persistence.jdbc.password" value="${DB_PASSWORD}"/>
<property name="hibernate.jdbc.time_zone" value="UTC"/>

Supply the credentials as protected runtime properties. For a prototype, schema generation can create the tables; production should use validation plus versioned migrations.

Implement reliable data access

Wrap EntityManager access in a repository and keep transaction boundaries in a service. A create operation commits and closes; a list operation reads inside a transaction, returns DTOs, and closes all resources.

Use named parameters rather than concatenating customer input into JPQL. The query remains portable and avoids accidental changes to the query shape.

List<Booking> findByEmail(EntityManager em, String email) {
    return em.createQuery(
        "SELECT b FROM Booking b WHERE b.email = :email ORDER BY b.startsAt",
        Booking.class)
        .setParameter("email", email)
        .getResultList();
}

Map rows explicitly, handle optimistic locking if concurrent operators edit bookings, and batch related lookups to avoid N+1 queries. Log failures without recording passwords or full personal details.

Build the interface for Australian use

The NetBeans GUI builder can create a Swing form with a bookings table, labelled fields, and validation messages beside each input. Keep the layout usable on a phone-sized browser if the interface later moves to Jakarta Faces, so customers can check bookings during a commute.

Display dates as day/month/year, offer early-morning and after-work slots, and show prices in AUD with a clear statement of whether GST is included. For a typical 10% GST calculation, store the taxable amount and tax separately when invoices require it.

If the operator is covered by the Privacy Act 1988, apply the Australian Privacy Principles: collect only necessary details, explain their purpose, secure the database, and prepare a breach-response process. Before business sign-off, the user acceptance testing guide can help structure realistic scenarios.

Test, package and release

Add JUnit tests for validation and service logic, then run integration tests against a disposable MySQL schema. Container-based MySQL is useful when Docker is available, but a dedicated test database on a developer workstation also works.

Use two concise checklists before release:

Build and persistence checks

  • Maven compiles with Java 21, and the chosen dependency versions are recorded.
  • The MySQL integration test creates data and cleans up.
  • Hibernate validates the schema instead of altering production tables.
  • Database credentials come from protected runtime configuration.

Interface and operations checks

  • Dates use day/month/year and times show the correct Australian zone.
  • Prices show AUD and identify GST treatment clearly.
  • Privacy notices match the data actually collected.
  • Logs, backups, restore steps, and monitoring have named owners.

Package the application and database migrations as versioned artefacts. When files move between a build server, developer, or Australian hosting provider, compare SHA-256 values on both ends; this explanation of post-transfer checksum verification shows how Python's hashlib can verify integrity. Publish the checksum through a trusted channel, configure logs and backups, and monitor database connectivity from the deployment location.