【问题标题】:Hibernate not getting correct records using query.list();Hibernate 没有使用 query.list() 获得正确的记录;
【发布时间】:2017-12-22 12:13:30
【问题描述】:

我正在构建一个使用HibernateMysql 的应用程序,我的整个数据库都有15 表。

这是问题所在:我开始将记录插入数据库并使用 query.list(); 查看它们以获取添加的记录,但是在获得“正确”结果一段时间后,我开始没有添加的最后一条记录,我再次添加,结果相同(之前显示的那个,但不是我添加的最后一个),我刷新并得到正确的记录,我再次刷新得到32 记录而不是43,我'我没有使用任何复杂的查询,只是一个带有条件的Select,你可以看到这真的很奇怪。

请注意,我正在保存对象,然后立即获取,所以插入后直接选择(我不知道这是否会导致 Mysql 出现问题),记录也完美地添加到数据库中,使用Mysql workbench我可以看到我的记录被正确添加到数据库中,我真的希望至少有人可以帮助我调试这个,因为我没有收到任何错误。

我正在使用 Hibernate 4.3.10 和 java 版本 1.8.0_131

这是一段代码,当我从我使用的一个实体中获取结果时,它“有时”会给我带来问题:

获取产品列表

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;
    }

插入产品的代码:

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;
        }
    }

这是 Product 实体类:

@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

这是我的休眠配置文件:

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

编辑:我试过session.flush()session.clear(),因为我虽然问题与兑现有关,但我仍然有同样的问题,我开始认为这是Mysql Workbench服务器的问题.

已经五天了,我不敢相信整个stackoverflow社区中没有人对此有丝毫的想法,这和我遇到的问题一样奇怪。

【问题讨论】:

  • 至少不是 Hibernate 专家,但我的猜测是缓存...您是否尝试过禁用所有 Hibernate 的缓存?您的配置没有显示任何特定的缓存,如果我没记错的话,Hibernate 有一些内置缓存。也可以在调用saveOrUpdate 后尝试session.flush()。我已经看到了一些需要这样做的奇怪行为(因为我们的代码做了一些愚蠢的事情)我在你的代码中没有看到任何让我觉得有问题的东西,但它可能有助于消除缓存问题。
  • 我刷新...你刷新什么?问题可能出在视图方面吗? 已经五天了,我不敢相信整个stackoverflow社区中没有人对此有丝毫的想法,这和我遇到的问题一样奇怪。这可能是奇怪,但并不像您自己在发布问题之前和之后 5 天没有更彻底地调试自己的问题那样奇怪。 PS我看到你正在吞下异常然后覆盖finally块中的返回值,我敢打赌这就是你假设即使发生错误也保存对象的原因。
  • @DraganBozanovic 通过刷新我的意思是我再次选择从数据库中获取结果,我认为这很清楚。还有什么让你认为我没有“调试”这个问题?不,我没有吞下异常,这是我在代码中留下 printStackTrace 并且我没有修改它的唯一部分,即使我正在打印堆栈跟踪,我也没有在任何其他方法中出现任何错误。另外我想我发表了评论说我在将结果显示到视图之前获取选择即直接打印值,所以问题不在于视图。
  • @DraganBozanovic “我敢打赌这就是为什么你认为即使发生错误也会保存对象的原因”,对象被保存相信我,我在发布这个问题之前验证了一百次,我'我没有假设任何事情,正如我在问题中所说,值总是保存到数据库中,我验证了使用 Mysql Workbench,我遇到的问题是选择。
  • @GherbiHicham 我没有看到您在其中添加产品并在一个块中列出产品的代码。你是单独打电话给他们的吗?

标签: java mysql hibernate


【解决方案1】:

发生这种情况确实很奇怪。乍一看,代码看起来不错,我看不出您获取数据的方式有任何问题。

您提到您在开始时得到了正确的响应,但过了一会儿又返回了不正确的数据。

我认为这是因为您每次都在创建一个新会话,而不是在完成后真正关闭它。

基本上,改变这个:

SessionsGenerator.getFactory().openSession();

收件人:

SessionsGenerator.getFactory().getCurrentSession();

使用 openSession() 时,需要显式刷新和关闭对象。这可能是您的问题的原因。

getCurrentSession() 如果一个新会话不存在,则打开一个新会话,并在完成后自动刷新并关闭该会话。

另外,将其添加到您的 hibernate.cfg.xml 中

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

否则,由于您没有配置为正确使用 getCurrentSession,您会发生异常。

另外,尝试调用

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

相反,如果您不想采用上述方法。

希望这能解决问题!

【讨论】:

    【解决方案2】:

    我认为随机结果是由于您的 select 语句缺少事务边界。 根据这个hibernate doc,你应该

    始终使用清晰的事务边界,即使是只读操作

    尝试更改您的代码并检查结果。

    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();
    }
    

    详细讨论可以found here

    【讨论】:

    • 我想我每次进行数据库操作时都在使用事务,你我之间唯一的区别是我使用的是匿名事务,你链接的讨论只讨论了必要性为每个数据库操作打开一个事务,正如您在我的代码中看到的那样,我正在这样做。
    • 是什么让您认为您的productsList() 中有“匿名交易”?就像在 SaveOrUpdate(Product product) 中一样,将显式事务添加到 productList() 会产生什么结果?
    • 据我了解,Hibernate docs session.getTransaction().commit() 和 saveOrUpdate() 方法中的 tx.commit() 非常相似,但第二个选项看起来更严格。
    • 你是对的。我对他的saveOrUpdate() 没有任何评论。我怀疑的是productsList()方法,里面没有明确的事务。
    • @Rocherlee 我尝试在ProductList() 和其他检索数据的方法中进行显式事务,但它仍然给我相同的行为,我认为声明事务之间没有任何区别变量然后提交它或使用 getTransaction() 代替
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-24
    • 1970-01-01
    • 1970-01-01
    • 2013-04-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-26
    相关资源
    最近更新 更多