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 ...

}

Kernel updates and grub settings in Ubuntu

ubuntu

Ubuntu tips for Linux kernel updates and grub settings:

I always try to install Ubuntu security or Linux kernel updates. But sometimes I get problems with graphics drivers and Linux kernels because my graphics driver is not compatible with latest Linux kernel. Then I have to boot with older Linux kernel version in Ubuntu. That’s why I wanted to write small tips.

  • Which Linux kernel version I have?

Open a terminal with Ctrl-Alt-T or from Unity menu
Type uname -sr press enter.  (-s name of the operating system, -r the operating system release level)

Linux 3.2.0-43-generic

  • List of  all installed Linux kernels in Terminal:

dpkg --list | grep linux-image

  • How can I see Ubuntu boot menu on startup?

Display your Grub is to press and hold the SHIFT button while booting.

  • Boot settings in grub: How can I boot with older Linux kernel?

Open grub in editor:

sudo gedit /etc/default/grub

#This is newest Linux kernel and default setting in Ubuntu
# deactivate
#GRUB_DEFAULT=0

# Set default for older Linux kernel (first entry is 0 in grub boot menu)
# 2 for Previous Linux versions 4 for me Linux 3.2.0-38-generic
# see your previous Linux versions in grub menu
GRUB_DEFAULT="2>4"

Save your changes and close editor.  Then type:

sudo update-grub

Without update-grub command your changes will not be applied! Reboot and you can see your selected Linux kernel with uname -sr command.

  • What happens if my GRUB_DEFAULT setting is wrong?

Don’t worry! Ubuntu will boot with the latest kernel.

Reference: www.askubuntu.com

Injectable Logger with CDI

In my Java EE projects I don’t like logger configuration in every classes such as below:

private Logger logger = Logger.getLogger(this.getClass().getName());

I want to use with @Inject annotation. Fortunately there is @Produces annotation for it (see CDI – JSR 299: Context and Dependency Injection). I’m writing a producer class then I can @Inject logger  everywhere as below:

package com.devsniper.demoapp.util;

import javax.enterprise.inject.Produces;
import javax.enterprise.inject.spi.InjectionPoint;

import org.apache.log4j.Logger;

/**
 * Logging producer for injectable log4j logger
 *
 * @author cem ikta
 */
public class LoggerProducer {
   /**
    * @param injectionPoint
    * @return logger
    */
    @Produces
    public Logger produceLogger(InjectionPoint injectionPoint) {
		return Logger.getLogger(injectionPoint.getMember().getDeclaringClass().getName());
    }
}

in classes:

@Inject
private transient Logger logger;

I am using log4j in producer class but this works well for java logger too. Transient keyword is important, without transient keyword you get the following error in GlassFish:

WELD-000054 Producers cannot produce non-serializable instances for injection into non-transient fields of passivating beans\\n\\nProducer\: Producer Method [Logger] with qualifiers [@Any @Default] declared as [[method] @Produces public  com.devsniper.demoapp.util.LoggerProducer.produceLogger(InjectionPoint)]\\nInjection Point\: [field] @Inject private com.desniper.demoapp.controller.UserController.logger