Customers Java Swing Application with Source Code

customersdesktop

I have developed the Customers Java Swing Application Demo. This application may be useful for developers who want to use Flamingo, Substance and SwingX.

Technology stack:

Model View Controller (MVC) vs Model View Presenter (MVP):

The Customers Java Swing Application Demo has MVC design pattern such as Java Swing. MVP is also popular for Desktop and RIA. Which is best, there are many discussions. Martin Fowler has written very good explanations for GUI Architectures. You may like to read.

Models and Services:

I have written entities with NamedQueries in JPA and Hibernate. The services are very simple with Generic AbstractService.

Screenshots:

Full source code on Bitbucket

* Customers Java Swing Application images and icons credit: iconsdb.com and icons8.com

Base entity class in JPA

hibernate

In Hibernate/JPA entities there are repeated fields and methods. Don’t repeat yourself and write a base class with @MappedSuperclass.

BaseEntity one: Minimal options

Common fields:

id: Table Id Column, Auto Increment. In entity model with @Id annotation.

version: Version column for Optimistic Lock has default ’0′ in table and managed from your database and EntityManager. In entity model with @Version annotation.

Common methods:

hashCode() and equals() very important. If you do not implement the methods you get problems later.

toString():I am using entity values for display e.g. customer.getFirstname(). It is more flexible for Swing, JavaFX or JSF components.


package com.devsniper.entitydemo.model;

import java.io.Serializable;

import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.Version;

/**
 * Base Entity
 *
 * @author cem ikta
 */
@MappedSuperclass
public abstract class BaseEntity implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id", nullable = false, columnDefinition = "BIGINT UNSIGNED")
    protected Long id;

    @Column(name = "version")
    @Version
    private Long version;

    public Long getId() {
        return id;
    }

    public Long getVersion() {
        return version;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (this.getId() != null ? this.getId().hashCode() : 0);

        return hash;
    }

    @Override
    public boolean equals(Object object) {
	if (this == object)
            return true;
        if (object == null)
            return false;
        if (getClass() != object.getClass())
            return false;

        BaseEntity other = (BaseEntity) object;
        if (this.getId() != other.getId() && (this.getId() == null || !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return this.getClass().getName() + " [ID=" + id + "]";
    }
}

BaseEntity two: with audit informations

Common fields: createdBy, createdAt, updatedBy, updatedAt

It is sometimes important to know when and by whom the data were saved. I save creation date, modification date and user informations in table. I have String for user informations, I save only username without foreign key, then I have no relations with user table. With @PrePersist and @PreUpdate you don’t need to set the date manual every time. Set the user informations(createdBy and updatedBy) in your controllers not in models. Business logic must always remain in the right place.

package com.devsniper.entitydemo.model;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.Size;

/**
 * Base Entity Audit
 *
 * @author cem ikta
 */
@MappedSuperclass
public abstract class BaseEntityAudit extends BaseEntity {

    @Column(name = "created_at")
    @Temporal(TemporalType.TIMESTAMP)
    private Date createdAt;

    @Size(max = 20)
    @Column(name = "created_by", length = 20)
    private String createdBy;

    @Column(name = "updated_at")
    @Temporal(TemporalType.TIMESTAMP)
    private Date updatedAt;

    @Size(max = 20)
    @Column(name = "updated_by", length = 20)
    private String updatedBy;

    public Date getCreatedAt() {
            return createdAt;
    }

    public void setCreatedAt(Date createdAt) {
            this.createdAt = createdAt;
    }

    public String getCreatedBy() {
            return createdBy;
    }

    public void setCreatedBy(String createdBy) {
            this.createdBy = createdBy;
    }

    public Date getUpdatedAt() {
            return updatedAt;
    }

    public void setUpdatedAt(Date updatedAt) {
            this.updatedAt = updatedAt;
    }

    public String getUpdatedBy() {
            return updatedBy;
    }

    public void setUpdatedBy(String updatedBy) {
            this.updatedBy = updatedBy;
    }

    /**
     * Sets createdAt before insert
     */
    @PrePersist
    public void setCreationDate() {
        this.createdAt = new Date();
    }

    /**
     * Sets updatedAt before update
     */
    @PreUpdate
    public void setChangeDate() {
        this.updatedAt = new Date();
    }

}

Sample usage of EntityBaseAudit:

If you use your table id columns with table name prefix e.g customer_id then use @AttributeOverride. Without prefix you remove @AttributeOverride.

@Entity
@Table(name = "customers")
@AttributeOverride(name = "id", column = @Column(name = "customer_id",
        nullable = false, columnDefinition = "BIGINT UNSIGNED"))
public class Customer extends BaseEntityAudit {

    // fields without id column ...

    public Customer() {
    }

    // getter and setter ...

}