Java Developer Tools

Audit - Rules - Hibernate

Description
This group contains audit rules that check for problems related to the use of Hibernate, an object/relational persistence and query service.

Rules:

Details

Always Use Identifier Names

Summary
You should always specify a name attribute for identifiers in Hibernate.

Description
This audit rule looks for identifier declarations that do not include a name attribute. If you do not specify a name attribute you allow Hibernate to manage database identity internally. For example, consider the following mapping declaration:

    <id column="CATEGORY_ID">
        <generator class="native"/>
    </id>

Hibernate will now manage the identifier values internally. But this technique has a serious drawback: you can no longer use Hibernate to manipulate detached objects effectively. So, you should always specify a name attribute in Hibernate. (If you don't like them being visible to the rest of your application, make the accessor methods private.)

Example
The following identifier declaration would be flagged because it does not include a name attribute:

    <id column="CATEGORY_ID">
        <generator class="native"/>
    </id>

you should use something like following:

    <id name="category" column="CATEGORY_ID">
        <generator class="native"/>
    </id>

Avoid Using "Field Access" Strategy

Summary
Access to properties via accessor methods is considered best practice by the Hibernate community.

Description
The access attribute allows you to specify how Hibernate should access property values of the POJO. The default strategy, "property", uses the property accessors (get/set method pair). The "field" strategy uses reflection to access the instance variable directly. Access to properties via accessor methods is considered best practice by the Hibernate community. It provides an extra level of abstraction between the Java domain model and the data model, beyond what is already provided by Hibernate. Properties are more flexible; for example, property definitions may be overridden by persistent subclasses.

This rule will only create a violation if both accessor methods are defined for the field. You can use the Declare Accessors for Persistent Fields rule to ensure that accessor methods exist.

Example
The value of the "access" attribute would be flagged:

    <property name="name" column="NAME" access="field">

Classes Should be Their Own Proxy

Summary
Every persistent class should be its own proxy.

Description
This audit rule looks for declarations of persistent classes in which a proxy is specified that is different from the class itself. The Hibernate framework recommends that every persistent class should be its own proxy.

Example
The following tag would be flagged because the proxy class is not the same as the class being described

    <class name="eg.Order" proxy="eg.IOrder">

It should be replaced by the following

    <class name="eg.Order" proxy="eg.Order">

Close Sessions Where Opened

Summary
Close sessions in the method where they are opened.

Description
This audit rule looks for methods in which a session is opened but not closed. The method Session.close() should be invoked in the same method as the method SessionFactory.openSession().

Example
The following method would be flagged because the opened session isn't closed.

    private void createMessage(String text, Date date) {
        ...
        Session session = sessionFactory.openSession();
        session.beginTransaction();

        Message message = new Message();
        message.setText(text);
        message.setDate(date);

        session.save(message);
        session.getTransaction().commit();
    }

To close the session, the method session.close() should be invoked in a finally block, as shown below

    private void createMessage(String text, Date date) {
        ...
        Session session = sessionFactory.openSession();
        try {
            session.beginTransaction();
            Message message = new Message();
            message.setText(text);
            message.setDate(date);

            session.save(message);
        } finally {
            session.close();
        }
    }

Declare Accessors for Persistent Fields

Summary
Declare accessor methods for all persistent fields of persistent class.

Description
This audit rule looks for fields in persistent classes for which either the getter or setter method is missing. Many other ORM tools directly persist instance variables, but Hibernate decouples this implementation detail from the persistence mechanism. Hibernate persists JavaBeans style properties, and recognizes method names of the form getFoo, isFoo and setFoo. Properties need not be declared public - Hibernate can persist a property with a default, protected or private get/set pair.

Example
The fields "text" and "nextMessage" would be flagged because they do not have getter or setter methods.

    public class Message {
        private Long id;
        private String text;
        public Message nextMessage;

        Message() {}

        public Message(String text) {
            this.text = text;
        }

        public Long getId() {
            return id;
        }

        private void setId(Long id) {
            this.id = id;
        }

        public String getText() {
            return text;
        }
    }

Declare Identifier Properties

Summary
Declare identifier properties on persistent classes.

Description
This audit rule looks for persistent classes that do not have an identifier property declared for them. Although Hibernate makes identifier properties optional, some functionality is available only to classes which declare an identifier property, including

1. Transitive reattachment for detached objects (cascade update or cascade merge)
2. Session.saveOrUpdate()
3. Session.merge()

Example
The following class would be flagged because there is no identifier field declared for it.

    public class Message {
        private String text;
        private Message nextMessage;

        Message() {}

        public Message(String text) {
            this.text = text;
        }

        public String getText() {
            return text;
        }

        public void setText(String text) {
            this.text = text;
        }

        public Message getNextMessage() {
            return nextMessage;
        }

        public void setNextMessage(Message nextMessage) {
        this.nextMessage = nextMessage;
        }
    }

Declare Private Identifier Setter

Summary
The setter method for an identifier property should be private.

Description
This audit rule looks for non-private methods used to set the value of an identifier field. The identifier field should only be assigned a value by Hibernate when the object is saved. By making the method private you ensure that other code cannot change the object's identity.

Example
The "setId" method would be flagged because it should be private.

    public class Message {
        private Long id;
        private String text;
        private Message nextMessage;

        Message() {}

        public Message(String text) {
            this.text = text;
        }

        public Long getId() {
            return id;
        }

        public void setId(Long id) {
                his.id = id;
        }
    }

Declare Type for java.util.Date Property

Summary
Declare type for java.util.Date property in configuration file.

Description
This audit rule looks for declarations of properties in the configuration files whose corresponding field has the type java.util.Date, but for which the property file does not contain a "type" attribute. Without a "type" attribute, Hibernate can't know if the property should map to an SQL date, a timestamp, or a time column.

Example
Given a class defined like the following

    public class Message {
        private Long id;
        private String text;
        private Date date;

        public Message () {}

        public Long getId() {
            return id;
        }

        private void setId(Long id) {
            this.id = id;
        }

        ...
    }

and a corresponding configuration file containing the following

    <hibernate-mapping>
        <class name="messages.Message" table="MESSAGES">
            <id name="id" column="MESSAGE_ID">
                <generator class="native"/>
            </id>
            <property name="date" column="MESSAGE_DATE"/>
            <property name="text"/>
        </class>
        ...
    </hibernate-mapping>

The property "date" would be flagged because it does not include the attribute "type". It should be replaced by something like the following

    <property name="date" type="timestamp" column="MESSAGE_DATE"/>

Deploy Mappings With Mapped Classes

Summary
Deploy the mapping files along with the classes they map.

Description
This audit rule looks for mapping files that are not in the same directory as the class being mapped. Having the mapping documents in a different directory makes it harder to keep the information in the file up to date and makes it harder to refactor the code when necessary. For example, the class com.eg.Foo should be mapped in the file com/eg/Foo.hbm.xml. This makes particularly good sense in a team environment.

Example
Given the following entry in the "hibernate.cfg.xml" file

    <mapping resource="helloMessage.hbm.xml"/>

The file "helloMessage.hbm.xml", containing the mapping entry below, would be flagged because it is not in the same directory as the mapped resource.

    <hibernate-mapping>
        <class
            name="hello.Message"
            table="MESSAGES">

            ...

        </class>
    </hibernate-mapping>

Implement a Zero-Argument Constructor

Summary
Implement a zero-argument constructor for persistent classes.

Description
This audit rule looks for persistent classes that do not explicitly implement a zero-argument constructor. The constructor does not need to be public, but it needs to exist so that Hibernate can instantiate the class using Constructor.newInstance().

Example
The following class would be flagged because it has no explicitly defined constructor.

    public class Message {
        private Long id;
        private String text;
        private Message nextMessage;

        public Message(String text) {
            this.text = text;
        }

        public Long getId() {
            return id;
        }
        private void setId(Long id) {
            this.id = id;
        }
    }

Invalid Property Type Mapping

Summary
Map a Hibernate property type only to the corresponding Java type.

Description
This audit rule looks for properties whose type is a standard type and checks to make sure that the actual type of the corresponding field is appropriate for the property's type. Non-standard types are ignored.

The following is a table of standard property types and the appropriate types to which they can be mapped.

Property Type                            Java Type
integer                                        int, java.lang.Integer
long                                            long, java.lang.Long
short                                        short, java.lang.Short
float                                            float, java.lang.Float
double                                        double, java.lang.Double
character                                    char, java.lang.Character
byte                                            byte, java.lang.Byte
boolean, yes_no, true_false    boolean, java.lang.Boolean
string, text                                java.lang.String
date, time, timestamp                java.util.Date
calendar, calendar_date            java.util.Calendar
big_decimal                                java.math.BigDecimal
locale                                        java.util.Locale
timezone                                    java.util.TimeZone
currency                                    java.util.Currency
class                                            java.lang.Class
binary                                        byte arrays
clob                                            java.sql.Clob
blob                                            java.sql.Blob

Example
Given a class Message containing the following field declaration

    private String text;

The folowing property in the file Message.hbm.xml would be flagged, because the property type "byte" doesn't correspond with Java type "String".

    <property name="text" column="MESSAGE_TEXT" type="byte"/>

Never Use the Identifier in equals() or hashCode()

Summary
Never ever use the database identifier in the equals() and hashCode() methods, because a transient object doesn't have an identifier value.

Description
This audit rule looks for uses of the identifier field in the implementation of either the equals() or hashCode() methods. A transient object doesn't have an identifier value because Hibernate will only assign a value when the object is saved. To implement equals() and hashCode(), use a unique business key, that is, compare a unique combination of class properties.

Example
The equals() method would be flagged because it uses the identifier property.

    public class Message {
        private Long id;
        private String text;
        private Message nextMessage;

        ...

        public boolean equals(Object obj) {
            if (obj instanceof Message) {
                Message message = (Message)obj;
                if (message.getId() == getId()) {
                    return true;
                }
            }
            return false;
        }
    }

One Class per Mapping File

Summary
Use one mapping file per persistent class.

Description
This audit rule looks for mapping files declaring mappings for multiple classes. Although it's possible to declare mappings for multiple classes in one mapping file by using multiple <class> elements, the recommended practice (and the practice expected by some Hibernate tools) is to use one mapping file per persistent class.

Example
Given a mapping file (*.hbm.xml) containing the following, the second "class" entry would be flagged:

    <hibernate-mapping>

        <class
            ...
        </class>

        <class
            ...
        </class>

    </hibernate-mapping>

Referenced Class Not Defined

Summary
Classes referenced in the configuration file (*.hbm.xml) should be declared.

Description
This audit rule checks for references within a Hibernate configuration file to classes that are not declared in the associated project. Hibernate will not work correctly if undeclared classes are referenced. Either the references should be removed or the classes should be declared.

Example
In the following entry (from a *.hbm.xml file), the value of the "name" attribute would be flagged

    <class
        name="class.not.exists" ... />

Rollback Transaction on Exception

Summary
Rollback transactions if an exception occurs.

Description
If the session throws an exception (including any SQLException), you should immediately rollback the transaction, call Session.close() and discard the session instance because certain methods of Session will not leave the session in a consistent state. This audit rule looks for places where the transaction will not be rolled back correctly.

Example
The following method would be flagged because it doesn't rollback the transaction if an exception occurs.

    private void transactionExample(...) {
        ...
        Session session = factory.openSession();
        Transaction tx = session.beginTransaction();
        // do some work
        ...
        tx.commit();
        ...
    }

It should be replaced by something like the following

    private void transactionExample(...) {
        ...
        Session session = factory.openSession();
        Transaction tx = null;
        try {
            tx = session.beginTransaction();
            // do some work
            ...
            tx.commit();
        } catch (Exception e) {
            if (tx != null) tx.rollback();
            throw e;
        } finally {
            session.close();
        }
        ...
    }

SQL Injection

Summary
SQL queries might be receiving data from the user or other unsafe sources.

Description
SQL Injection occurs when the user is able to enter data directly into SQL queries.

To detect violations, this audit rule searches the code for SQL queries such as java.sql.Statement.execute(..) and traces where the query data could have come from. In cases where the source of the query is user input, such as data from a servlet request, javax.servlet.ServletRequest.getParameter(java.lang.String), or from a SWT Text widget, org.eclipse.swt.widgets.Text.getText(), a violation is created.

These two sets of methods, the locations where tainted user data can come from and the methods used to query the database, are editable by the user.If methods are missing that are in a common package (such as java.lang.*), please let CodePro support know.

Also note, the SQL query methods for Hibernate and Persistence frameworks have been added.

Security Implications
Successful SQL Injection attacks can potentially drop tables, update the database in a malicious manner and even gain administrator access.

Example
The invocation of the method executeQuery(..) would be flagged as a violation since it uses the first name information passed from a servlet request:

    ServletRequest servletRequest;
    Connection connection;
    Statement statement;
    
    servletRequest = ...;
    connection = DriverManager.getConnection("www.example.com", "myUserName", "myPassword");
    statement = connection.createStatement();
    
    String firstName = req.getParameter("firstName");
    String query = "SELECT * FROM user_data WHERE firstName = '" + firstName + "'";
    statement.executeQuery(query);

Use "Nullable" Type for Identifier Properties

Summary
Use a "nullable" type for identifier properties of persistent classes.

Description
Identifier properties of persistent classes should be 'synthetic' (generated, with no business meaning) and of a non-primitive type. This audit rule looks for identifier properties with a primitive type. For maximum flexibility, use java.lang.Long or java.lang.String.

Example
The following class would be flagged because it has a primitive-valued identifier field.

    public class Message {
        private int id;
        private String text;
        private Message nextMessage;

        Message() {}

        public Message(String text) {
            this.text = text;
        }

        public int getId() {
            return id;
        }
        private void setId(int id) {
            this.id = id;
        }
    }

Use Interfaces for Collection Attributes

Summary
Hibernate requires that collection-valued properties be typed to an interface such as java.util.Set or java.util.List and not to an actual implementation such as java.util.HashSet (this is a good practice).

Description
Hibernate requires interfaces for collection-typed attributes. You must use java.util.Set rather than HashSet, for example. At runtime, Hibernate wraps the HashSet instance with an instance of one of Hibernate's own classes. (This special class isn't visible to the application code). It is good practice to program to collection interfaces, rather than concrete implementations.

Example
childCategories would be flagged:

    public class Category {
        private String name;
        private Category parentCategory;
        private HashSet childCategories = new HashSet();

        public Category() { }

        ...
    }

Use Only Non-Final Persistent Classes

Summary
Use only non-final persistent classes.

Description
This audit rule looks for persistent classes for which a proxy cannot be created. The use of proxies, a central feature of Hibernate, depends on the persistent class being either non-final, or the implementation of an interface that declares all of the public methods.

You can persist final classes that do not implement an interface with Hibernate, but you won't be able to use proxies for lazy association fetching - which will limit your options for performance tuning.

Example
The following persistent class would be flagged because it is final.

    public final class Message {
    ...
    }

Use Only Static Inner Classes

Summary
Use only static inner persistent classes.

Description
This audit rule looks for inner classes that are declared to be persistent and checks to make sure that they are static. Hibernate cannot persist non-static inner classes.

Example
If the mapping file OuterClass$NestedClass.hbm.xml contains

    <class
        name="OuterClass$NestedClass" ... >

then the persistent class NestedClass would be flagged because it non-static:

    public final class OuterClass {
        ...

        public class NestedClass {
            ...
        }
    }

Use Session-per-request Pattern

Authentication required

You need to be signed in with Google+ to do that.

Signing you in...

Google Developers needs your permission to do that.