Development Best Practice: Java Collections

In order to encapsulate business logic and also from the other side letting other objects outside of our class to trace the collection of items related to your business logic, best practice is to use the Collection as an internal variable inside the class and provide a outside class which basically wraps the Collection, and then that wrapper class should implement Iterable interface. which means in simple words, just implementing the iterator () method. please see below example:

public class MyWrapperClass  implements Iterable{

 private final List<MyBeanObject> listOfBeans= new ArrayList&lt;&gt;();
 public void add(MyBeanObject p){
//TODO: implement add using Collection ...
}
 public void replace(MyBeanObject p) {
        // TODO : implement using collection reference...
}

 public void remove(MyBeanObject p) {
       // TODO: implement remove using collection specific implementation...
 }

@Override
public Iterator iterator() {
    return listOfBeans.iterator();
}

import static

you may face a situation when you need some static members and methods from a few classes, but you prefer not to mention those full qualification class name as a reference for getting access to static fields/or methods. The solution is by using import static, instead of regular import .

one of the most common examples is JUnit methods.

import static org.junit.Assert.*;
import org.junit.Test;

public class MyObjectTest {

    @Test
    public void shouldReplaceItem() throws Exception {
        fail("Not yet implemented");
    }

}

you can see by adding static import at the beginning, calling the fail method or other Assert-related methods could be easier and more readable.

Reference: Java Oracle Documentation.

“final” Keyword Hints

In java you can use Final keyword in 3 contexts:

  1. Variables

  2. Methods

  3. Classes

Final Variables:

make it constant and it can’t change after it was init. change only one time.

examples:

public class KeywordTest {

    /*
     * have a final keyword for variables.
     */
    private final String str1 = "str init'ed!";
    private final int number = 12;

    public void finalChanger() {

        String str2 = str1;
        str2 = str2.toUpperCase();

        // below line can't be compiled!
        // str1 = str2;

        int num2 = number;
        num2 += 12;

        System.out
                .println("contents are copied and copies were modified,"
+" the first contents referenced with final keywords, are still the same.");
        System.out.println(str2 + "");
        System.out.println(num2 + "");
    }

    /**
     * @param args
     */
    public static void main(String[] args) {

        new KeywordTest().finalChanger();
    }

}

Hint: you can init the final variables in constructor and keep them non-initialized before hand, please see the example below:

you can init the final variables in the constructor and keep them non-initialized before hand, please see the example below:

you can init the final variables in the constructor and keep them non-initialized before hand, please see the example below:

public class KeywordTest {

    public KeywordTest(int number) {
        this.CODE = number;
    }
    
    private final int CODE;

    public void finalChanger() {
        int num2 = CODE;
        num2 += 12;

        System.out.println(num2 + "");
    }

    /**
     * @param args
     */
    public static void main(String[] args) {

        new KeywordTest(12).finalChanger();
    }

}

Final Methods:

if you want to force inherited class/children to use some methods in Parent class without modifying it, this keyword is useful.

Parent Class

public abstract class Parent {
    
    /**
     * final method in parent class.
     */
    public final void dontOverride(){
        System.out.println("In Parent.class");
        System.out.println("dontOverride() one is implemneted in parent class and can't be overriden.");
    }
    
    /**
     * implemented method in parent part.
     */
    public void method1(){
        System.out.println("In Parent.class");
        System.out.println("Method()1 is implemneted in parent class.");
    }
    
    /**
     * this is the abstract method signature in parent part.
     */
    public abstract void method2();
    
}

Child class:

public class Child extends Parent {

    @Override
    public void method2() {
        System.out.println("in Child.class");
        System.out.println("Method()2 is implemneted in Child class, and it was abstract method in Parent class.");

    }

    @Override
    public void method1() {
        System.out.println("in Child.class");
        System.out.println("Method()1 was implemneted in Parent class, and again in Child class was overriden.");

    }

    public void explanation() {
        System.out.println("in Child.class");
        System.out
                .println("Parent.dontOverride() Method can't be accessible to change its signration in other subclasses, theonly way isto use the method by calling the parent class instance.");

        System.out.println("Calling Parent.dontOverride() in Child class using parent reference. ");
        super.dontOverride();
    }

}

Testing Program class

public class ProgramTest {
    public static void main(String[] args) {
        Child c = new Child();
        System.out.println("-------------------");
        c.method1();
        System.out.println("-------------------");
        c.method2();
        System.out.println("-------------------");
        System.out
                .println("Calling final parent method using Child reference, since it's still accibel in the hirarchial order,"
                        + " but it can;t be changed/updated.");
        c.dontOverride();
        System.out.println("-------------------");
        c.explanation();
    }
}

Final Classes:

make the class non-extendable. so none of its functionalities can’t be overridden.

Hbm2DLL.auto

The first thing that we should know about this Hibernate Configuration option is, never ever use that (Hbm2DLL.auto) option in production region. However, it can increase development speed in lower/dev regions, and that’s a good practice for large project that wanted to start from scratch – if they have a standard for database schema, and their methodology is Code-First development, but since there is no guarantee in data integrity for existed database schemas, it’s better and safer to avoid using this option in production region. So for legacy application, DON’T  use this option.

Validate: it won’t change the existed tables, but it validate and make sure the mapping file matches what we already have in database.

update: won’t drop, But it will add if the table is there/

create: create tables that are not in db, and drop the one which is already existed and create them again.

create-drop: like create option but it will drop all the tables it created when the SessionFactory closes.

This feature is useful only for development. Create your POJO classes, and then their mapping and that’s all. Then you can set this item in the hibernate.cfg.xml. Then go to database and export the DDL and put the DDL into your actual production environment.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
                                         "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
 <session-factory>
  <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
  <property name="hibernate.connection.password">***********</property>
  <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/MyDataBaseName</property>
  <property name="hibernate.connection.username">appuser</property>
  <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
  <property name="hibernate.show_sql">true</property>
  <property name="hibernate.use_sql_comments">true</property>
  <property name="hibernate.hbm2ddl.auto">create</property>
  <property name="hibernate.format_sql">true</property>
  <mapping resource="com/navid/practice/hibernate/User.hbm.xml"/>
  <mapping resource="com/navid/practice/hibernate/Plan.hbm.xml"/>
 </session-factory>
</hibernate-configuration>

Traditional Hibernate Issues (POJO): Part#4: ERROR: Unknown column

if you face “ERROR: Unknown column” exception in middle of Hibernate, check the XML mapping file and make sure the name of the pre-existed database tables are matched with what you have mentioned in the XML mapping file, for example:

Oct 29, 2016 2:09:22 PM org.hibernate.dialect.Dialect 
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
Hibernate: /* insert com.navid.practice.hibernate.User */ insert into USERS (NAME, TOTAL) values (?, ?)
Oct 29, 2016 2:09:22 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
WARN: SQL Error: 1054, SQLState: 42S22
Oct 29, 2016 2:09:22 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
ERROR: Unknown column 'NAME' in 'field list'
org.hibernate.exception.SQLGrammarException: could not execute statement
at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:63)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:97)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:207)
at org.hibernate.dialect.identity.GetGeneratedKeysDelegate.executeAndExtract(GetGeneratedKeysDelegate.java:57)
at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:42)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2840)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3411)
at org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:81)
at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:623)
at org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:277)
at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:258)
at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:303)
at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:318)
at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:275)
at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:182)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:113)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:192)
at org.hibernate.event.internal.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:38)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:177)
at org.hibernate.event.internal.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:32)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:73)
at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:674)
at org.hibernate.internal.SessionImpl.save(SessionImpl.java:666)
at org.hibernate.internal.SessionImpl.save(SessionImpl.java:661)
at com.navid.practice.hibernate.Program.main(Program.java:23)
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'NAME' in 'field list'
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:425)
at com.mysql.jdbc.Util.getInstance(Util.java:408)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:943)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3970)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3906)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2524)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2677)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2549)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1861)
at com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2073)
at com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2009)
at com.mysql.jdbc.PreparedStatement.executeLargeUpdate(PreparedStatement.java:5098)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1994)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:204)
... 22 more

Solution:

in the XML mapping file for the related table as mentioned in the exception , I had:

 <hibernate-mapping>
    <class name="com.navid.practice.hibernate.User" table="USERS">
        <id name="id" type="int">
            <column name="ID" />
            <generator class="assigned" />
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        <property name="total" type="int">
            <column name="TOTAL" />
        </property>
    </class>
</hibernate-mapping>

AHA, now we found the culprit … so update the NAME to USERNAME , the field that we already defined in database side and re-run the application again.

found the issue in the highlighted part and updated it with what I have in the database side for that column. After fixing this issue and running the application, then I had the clean run:

INFO: HHH000115: Hibernate connection pool size: 20 (min=1)
Oct 29, 2016 2:13:01 PM org.hibernate.dialect.Dialect 
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
Hibernate: /* insert com.navid.practice.hibernate.User */ insert into USERS (USERNAME, TOTAL) values (?, ?)
Oct 29, 2016 2:13:02 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl stop
INFO: HHH10001008: Cleaning up connection pool [jdbc:mysql://localhost:3306/protein_tracker]

Traditional Hibernate Issues (POJO): Part#3 : can’t find the database:

can’t find the database:

INFO: HHH000115: Hibernate connection pool size: 20 (min=1)
 Oct 29, 2016 2:05:15 PM org.hibernate.dialect.Dialect 
 INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
 Hibernate: /* insert com.navid.practice.hibernate.User */ insert into USERS (NAME, TOTAL) values (?, ?)
 Oct 29, 2016 2:05:15 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
 WARN: SQL Error: 1046, SQLState: 3D000
 Oct 29, 2016 2:05:15 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
 ERROR: No database selected
 org.hibernate.exception.GenericJDBCException: could not execute statement
 at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:47)
 at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111)
 at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:97)
 at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:207)
 at org.hibernate.dialect.identity.GetGeneratedKeysDelegate.executeAndExtract(GetGeneratedKeysDelegate.java:57)
 at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:42)
 at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2840)
 at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3411)
 at org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:81)
 at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:623)
 at org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:277)
 at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:258)
 at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:303)
 at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:318)
 at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:275)
 at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:182)
 at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:113)
 at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:192)
 at org.hibernate.event.internal.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:38)
 at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:177)
 at org.hibernate.event.internal.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:32)
 at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:73)
 at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:674)
 at org.hibernate.internal.SessionImpl.save(SessionImpl.java:666)
 at org.hibernate.internal.SessionImpl.save(SessionImpl.java:661)
 at com.navid.practice.hibernate.Program.main(Program.java:23)
 Caused by: java.sql.SQLException: No database selected
 at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:964)
 at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3970)
 at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3906)
 at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2524)
 at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2677)
 at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2549)
 at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1861)
 at com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2073)
 at com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2009)
 at com.mysql.jdbc.PreparedStatement.executeLargeUpdate(PreparedStatement.java:5098)
 at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1994)
 at org.hibernate.engine.jdb

Solution:

check the configuration xml file and you have to make sure, the database is mentioned in the url.

jdbc:mysql://localhost:3306/

Mine didn’t have that, so I added.

jdbc:mysql://localhost:3306/MyPersonalDatabaseName

Traditional Hibernate Issues (POJO): Part#1 org.hibernate.MappingException: Unknown entity

Unknown Entity exception might have a verity of reasons and causes, however, when you’re using POJO and XML files, since there is no Entity tags and mismatching between JPA nad Hibernate class tags, the reason of this exception might be a little bit challenging. when you’re using POJO with newer version of Hibernate, the main reason might be related to the way you are initiating SessionFactory.something like below…

 

INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
 org.hibernate.MappingException: Unknown entity: com.navid.practice.hibernate.User
 at org.hibernate.metamodel.internal.MetamodelImpl.entityPersister(MetamodelImpl.java:620)
 at org.hibernate.internal.SessionImpl.getEntityPersister(SessionImpl.java:1605)
 at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:104)
 at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:192)
 at org.hibernate.event.internal.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:38)
 at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:177)
 at org.hibernate.event.internal.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:32)
 at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:73)
 at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:674)
 at org.hibernate.internal.SessionImpl.save(SessionImpl.java:666)
 at org.hibernate.internal.SessionImpl.save(SessionImpl.java:661)
 at com.navid.practice.hibernate.Program.main(Program.java:23)

the issue was related to the version of Hibernate that I had, 5.x and the code that I wrote for init the SessionFactory:

public class HibernateUtilities {

private static ServiceRegistry svcReg = null;
 private static SessionFactory sessionFactory = null;

static {

try {
 Configuration cfg = new Configuration().configure();

svcReg = new StandardServiceRegistryBuilder().applySettings(cfg.getProperties()).build();
 sessionFactory = cfg.buildSessionFactory(svcReg);

} catch (HibernateException e) {
 System.out.println("An Error in init the SessionFactory!");
 }

}

Solution:

the issue could be resolved just by changing the SessionFactory creation line …

sessionFactory = cfg.buildSessionFactory();