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.