RMagen
RMagen

Reputation: 622

hibernate call takes more then a minute

I have a very small DB with 5 tables and 2 records every thing was working fine until i did a DB change and run the "hibernate code generation " in eclipse to generate the hibernate files automatically now when I call a web service that uses hibernate 5 it takes more then 2 minute to perform this record

this.sessionFactory = this.configuration.buildSessionFactory(this.sr);

UPDATE: i forgot to mention that if i take the war and put it on a tomcat server (not my eclipse ) , it takes few seconds

this is the full code

Configuration configuration;
ServiceRegistry sr;
SessionFactory sessionFactory;

and in the init method

this.configuration = new Configuration().configure();
configuration.addClass(Surveys.class);
configuration.addClass(MembersAnswers.class);
configuration.addClass(Categories.class);
configuration.addClass(PossibleAnswers.class);
configuration.addClass(Questions.class);
configuration.addClass(CategoriesAnswers.class);
this.sr = new StandardServiceRegistryBuilder().applySettings( 
this.configuration.getProperties()).build();
this.sessionFactory = this.configuration.buildSessionFactory(this.sr);

this is my configuration gile

<session-factory>
    <property name="hibernate.bytecode.use_reflection_optimizer">false</property>
    <property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
    <property name="hibernate.connection.password">password</property>
    <property name="hibernate.connection.url">jdbc:postgresql://xxxxxxxxx/yyy</property>
    <property name="hibernate.connection.username">user</property>
    <property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
    <property name="hibernate.enable_lazy_load_no_trans">true</property>
    <property name="hibernate.search.autoregister_listeners">true</property>
    <property name="hibernate.validator.apply_to_ddl">false</property>
    <mapping class="DBFiles.MembersAnswers"/>
    <mapping class="DBFiles.PossibleAnswers"/>
    <mapping class="DBFiles.CategoriesAnswers"/>
    <mapping class="DBFiles.Questions"/>
    <mapping class="DBFiles.Categories"/>
    <mapping class="DBFiles.Surveys"/>
</session-factory>

here is an example for one of the files that was generated automaticaly

@Entity
@Table(name = "categories", schema = "edi_ms")
public class Categories implements java.io.Serializable {

private long categoryId;
private String categoryName;
private Date effectiveDate;
private Date expirationDate;
private Set<CategoriesAnswers> categoriesAnswerses = new HashSet<CategoriesAnswers>(0);

public Categories() {
}

public Categories(long categoryId, String categoryName, Date effectiveDate) {
    this.categoryId = categoryId;
    this.categoryName = categoryName;
    this.effectiveDate = effectiveDate;
}

public Categories(long categoryId, String categoryName, Date effectiveDate, Date expirationDate,
        Set<CategoriesAnswers> categoriesAnswerses) {
    this.categoryId = categoryId;
    this.categoryName = categoryName;
    this.effectiveDate = effectiveDate;
    this.expirationDate = expirationDate;
    this.categoriesAnswerses = categoriesAnswerses;
}

@Id

@Column(name = "category_id", unique = true, nullable = false)
public long getCategoryId() {
    return this.categoryId;
}

public void setCategoryId(long categoryId) {
    this.categoryId = categoryId;
}

@Column(name = "category_name", nullable = false, length = 20)
public String getCategoryName() {
    return this.categoryName;
}

public void setCategoryName(String categoryName) {
    this.categoryName = categoryName;
}

@Temporal(TemporalType.DATE)
@Column(name = "effective_date", nullable = false, length = 13)
public Date getEffectiveDate() {
    return this.effectiveDate;
}

public void setEffectiveDate(Date effectiveDate) {
    this.effectiveDate = effectiveDate;
}

@Temporal(TemporalType.DATE)
@Column(name = "expiration_date", length = 13)
public Date getExpirationDate() {
    return this.expirationDate;
}

public void setExpirationDate(Date expirationDate) {
    this.expirationDate = expirationDate;
}

@OneToMany(fetch = FetchType.LAZY, mappedBy = "categories")
public Set<CategoriesAnswers> getCategoriesAnswerses() {
    return this.categoriesAnswerses;
}

public void setCategoriesAnswerses(Set<CategoriesAnswers> categoriesAnswerses) {
    this.categoriesAnswerses = categoriesAnswerses;
}

Upvotes: 2

Views: 368

Answers (2)

RMagen
RMagen

Reputation: 622

we think the problem was that since the server is located close to the DB is was working OK also worked on a PC located close to the DB

in order to fix the problem i added

<property name="hibernate.temp.use_jdbc_metadata_defaults">false</property>

to the hibernate.cfg.xml to prevent hibernate to go to the DB and validate the structure.

this fixed my issue

Upvotes: 1

Julius Krah
Julius Krah

Reputation: 422

Start by looking at what's happening inside the SessionFactory. Hibernate offers a JMX connector, see documentation here.

If you enable the hibernate.generate_statistics configuration property, Hibernate will expose a number of metrics via SessionFactory.getStatistics(). Hibernate can even be configured to expose these statistics via JMX. This way, you can get access to the Statistics class which comprises all sort of second-level cache metrics.

Then you can start to look into your hotspots and how to refactor them. You really need to begin with gathering some more metrics. Right now it could be anything, including GC problems.

Alternatively
It appears SessionFactory is getting created several times. You need to ensure that SessionFactory gets created once.

public class HibernateUtil {
  // Private constructor; Class cannot be initialized
  private HibernateUtil() {}

  private static final SessionFactory sessionFactory;
  // create sessionFactory only once   
  static {
    // A SessionFactory is set up once for an application!
    final StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
        .configure() // configures settings from hibernate.cfg.xml
        .build();
    try {
      sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();
    } catch (Exception e) {
      // The registry would be destroyed by the SessionFactory, but we had trouble building
      // the SessionFactory so destroy it manually.
      StandardServiceRegistryBuilder.destroy( registry );
    }
  }

  public static SessionFactory getSessionFactory() {
    return sessionFactory;
  }
}

Now you can call the initialized SessionFactory in your code:

Session session = HibernateUtil.getSessionFactory().openSession();

This way Hibernate is already initialized on container startup. Hope this helps.

Upvotes: 1

Related Questions