7

I'm building an application that uses Hibernate and Mysql, My entire databse has 15 tables.

Here is the problem: I start inserting records into the database and viewing them using query.list(); to get the added records, howerver after a while of getting "correct" results, I start not having the last record I added, I add again and it's the same(the one that was showing before shows but not the last one I added), I refresh and I get the right records, I refresh again and I get 32 records instead of 43, I'm not using any complicated queries just a Select with a condition, as you can see this is really weird.

Note that I'm saving the objects and then imidiately fetching, so an insert directly followed by a select(I don't know if that can cause problems in Mysql), the records are also added into the databse perfectly, using Mysql workbench I can see that my records are added corretly into the database, I really hope someone can atleast help me debug this, because I'm not getting any errors.

I'm using Hibernate 4.3.10 and java version 1.8.0_131

Here is a piece of code that "sometimes" gives me problems when getting the results from one of the entities that I use:

getting a list of Products:

public static List<Product> productsList() {
        //singleton factory object
        SessionsGenerator FactoryObject = new SessionsGenerator();
        Session session = SessionsGenerator.getFactory().openSession();
        List<Product> list = new ArrayList<>();
        try {
            list = session.createQuery("from Product where deleted= false").list();
            System.out.println("-------------- list product: "+list); // testing from console here I get the same results on the user interface, so it can't be a Javafx problem.
        } finally {
            session.close();
        }
        return list;
    }

Code for inserting a product:

public static boolean SaveOrUpdate(Product product) {
        SessionsGenerator FactoryObject = new SessionsGenerator();
        Session session = SessionsGenerator.getFactory().openSession();
        try {
            session.beginTransaction();
            session.saveOrUpdate(product);
            session.getTransaction().commit();
        } catch (Exception e) {
            return false;
        } finally {
            session.close();
            return true;
        }
    }

Here is the Product entity class:

@Entity
@Table(name = "Product")
public class Product{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id", nullable = false)
    int id;
    @Column(name = "code", nullable = false)
    String code;
    @Column(name = "matricule", nullable = false)
    String matricule;
    @Column(name = "marque", nullable = false)
    String marque;
    @Column(name = "type", nullable = false)
    String type;
    @OneToMany(targetEntity = Facture.class, mappedBy = "product", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<Facture> factures;
    @OneToMany(targetEntity = Achat.class, mappedBy = "product", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<Achat> achats;
    @Column(name = "deleted", nullable = false)
    boolean deleted;

    public Product() {
    }

    public Product(String code, String matricule, String marque,String type) {
        this.code = code;
        this.matricule = matricule;
        this.marque = marque;
        this.type = type;
        this.deleted = false;
    }
//setters and getters

Here is my hibernate configuration file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
  <session-factory>
    <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.connection.username">root</property>
    <property name="hibernate.connection.password">root</property>
    <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/gestioncommerciale</property>
    <property name="connection_pool_size">1</property>
    <property name="hbm2ddl.auto">update</property>
    <property name="show_sql">true</property>
    <property name="hibernate.current_session_context_class">thread</property>
  </session-factory>
</hibernate-configuration>

Edit: I tried session.flush() and session.clear(), cause I though the problem has to do with cashing, but I still have the same problem, I'm starting to think this is a problem with the Mysql Workbench server.

It has been five days, I can't believe no one in the entire stackoverflow community even has the slightest idea about this, this is as strange as the problem I'm having.

Gherbi Hicham
  • 2,416
  • 4
  • 26
  • 41
  • 2
    Not a Hibernate expert in the least but my guess is caching... have you tried disabling all of Hibernate's caching? Your config shows nothing caching specific and if I recall correctly Hibernate has some built-in caching. Also maybe try `session.flush()` after calling `saveOrUpdate`. I've seen some weird behavior where that was required (because we had code doing something dumb) I don't see anything in your code that strikes me as iffy but it might help eliminate caching issues. – Daniel Bickler Jul 17 '17 at 20:45
  • 2
    _I refresh ..._ What do you refresh? Could the problem be on the view side? _It has been five days, I can't believe no one in the entire stackoverflow community even has the slightest idea about this, this is as strange as the problem I'm having._ This may be _strange_, but not as strange as that you yourself didn't debug your own issue more thoroughly before posting the question and 5 days after that. PS I see you're swallowing exception and then overriding the return value in the `finally` block, I bet that's the reason why you assume that the object is saved even if an error occurs. – Dragan Bozanovic Jul 24 '17 at 11:55
  • @DraganBozanovic By refresh I mean I do another select to get the results from the database I think that's pretty clear. Also What makes you think I didn't "debug" the issue? And no I'm not swallowing exceptions that's the only part where I left the printStackTrace in my code and I didn't modify it , I'm just not having any errors in any other method eventhough I'm printing the stack trace. Also I think I made a comment saying that I'm printing the value directly when I'm getting the select ie before the displaying the results to the view, so no the problem is not about the view. – Gherbi Hicham Jul 24 '17 at 16:10
  • @DraganBozanovic "I bet that's the reason why you assume that the object is saved even if an error occurs", the object is saved trust me, I verified that a hundred times before posting this question, I'm not assuming anything, as I said in the question, the value always gets saved into the database, I verified that using the Mysql Workbench, the problem I'm getting is with the select. – Gherbi Hicham Jul 24 '17 at 16:15
  • Can you post your entire project (Java&SQL) somewhere, and people can join with debug – VinhNT Jul 25 '17 at 02:09
  • 1
    @GherbiHicham i don't see the code where you are adding a product and listing the product in one block. are you calling them separately? – Itherael Jul 25 '17 at 22:14
  • @Itherael I'm listing the product right after I add a product, yes I'm calling both methods that do that in a one block of code one after another. – Gherbi Hicham Jul 26 '17 at 09:24
  • Are you sure that you use the single Hibernate SessionFactory? What is new SessionsGenerator()? – Andriy Slobodyanyk Jul 27 '17 at 10:57
  • @AndriySlobodyanyk Yes, I'm wrote the SessionsGenerator class as a singleton, a SesionFactory object can only be made once. – Gherbi Hicham Jul 27 '17 at 16:43
  • Hi, can you just show the sql which is created by hibernate to get the list of products? and also run the same query on your MySql database. – n j Jul 30 '17 at 11:29

2 Answers2

1

It's definitely strange that this is happening. At first glance, the code seems fine and I don't see any issues with how you're fetching the data.

You mentioned that you are getting the correct responses in the beginning but then after awhile the incorrect data is returned.

I think this is because you're creating a new session each time and not actually closing it once you're done.

Basically, change this:

SessionsGenerator.getFactory().openSession();

To:

SessionsGenerator.getFactory().getCurrentSession();

When using openSession(), you need to explicitly flush and close the object. This may be the cause of your problem.

getCurrentSession() opens a new session if one does not exist and also automatically flushes and closes the session once done.

Also, add this into your hibernate.cfg.xml

<session-factory>
<!--  Put other elements here -->
<property name="hibernate.current_session_context_class">
          thread
</property>
</session-factory>

otherwise, you'll get exceptions occurring because you haven't configured to use getCurrentSession properly.

Additionally, try calling

session.flush(); 
session.close(); 

instead, if you don't want to take the above approach.

Hopefully, that fixes the issue!

0

I think random result is due to lack of transaction boundary for your select statement. According to this hibernate doc, you should

Always use clear transaction boundaries, even for read-only operations

Try to change your code and check the result.

Transaction tx = null;
try {
    tx = session.beginTransaction();
    list = session.createQuery("from Product where deleted= false").list();
    tx.commit();
} catch (Exception e) {
      if (tx != null) tx.rollback();
} finally {
      session.close();
}

A detailed discussion could be found here

Rocherlee
  • 2,536
  • 1
  • 20
  • 27
  • I think I'm using a transaction everytime I make a database operation, the only difference between you and me is that I'm using an anonymous transaction, the disscussion you linked only talks about the necessity of opening a transaction for each database operation, and as you can see in my code I'm doing that. – Gherbi Hicham Jul 27 '17 at 16:51
  • What make you think there is "an anonymous transaction" in your `productsList()`? What's the result when you add an explicit transaction into `productList()` just like you did in `SaveOrUpdate(Product product)`? – Rocherlee Jul 28 '17 at 01:59
  • As far as I understand Hibernate docs session.getTransaction().commit() and tx.commit() in saveOrUpdate() method are pretty same but the second option looks more strict. – Andriy Slobodyanyk Jul 28 '17 at 08:48
  • You're right. I had no comment on his `saveOrUpdate()`. What I doubt is the `productsList()` method, there is no explicit transaction inside. – Rocherlee Jul 28 '17 at 08:57
  • @Rocherlee I tried doing an explicit transaction in `ProductList()` and the other methods that retrieve data but it still gives me the same behaviour, and I don't think there is any difference between declaring a transaction variable and then commiting it or using `getTransaction()` instead – Gherbi Hicham Jul 30 '17 at 12:24