【问题标题】:Retrieve a row data from database using JPQL使用 JPQL 从数据库中检索行数据
【发布时间】:2016-12-03 22:57:26
【问题描述】:

我编写了一个 Java EE 应用程序来转换货币。用户输入要转换的值、“from”货币和“to”货币,从数据库表中检索转换率。

! [Netbeans 中的表格片段]https://s16.postimg.org/8m242gyyd/Screen_Shot_2016_12_03_at_23_45_23.png

我的货币控制器有以下代码:

public double convertTo(double value, String fromCur, String toCur) {
    TypedQuery<Rate> query = em.createQuery(""
            + "SELECT c FROM Rate c WHERE c.fromCur = 'BRA' AND c.toCur = 'EUR'", Rate.class);

    query.setParameter("tocurrency", toCur);
    query.setParameter("fromcurrency", fromCur);

    Rate result = query.getSingleResult();

    if (result == null) {
        throw new EntityNotFoundException("Can't find rate");
    }

    return value * result.getValue();

}

例如,我的目标是获取从“BRA”到“EUR”的汇率并计算转换后的金额并返回。当我运行应用程序时,我得到了异常:

getsinglerresult() 没有检索到任何实体

必须有一种更简单的方法来从数据库中检索速率以使用实体管理器计算此转换,但我找不到合适的查询方法或 JPA 解决方案。有什么建议吗?

java实体Rate.java的代码如下:

package currency.model;

import java.io.Serializable;
import java.math.BigDecimal;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

/**
 *
 * @author teowey
 */
@Entity
public class Rate implements ConversionDTO, Serializable {


@Id
@GeneratedValue
private Integer conversionid;

private double rate;
private BigDecimal value;

private String fromCur;
private String toCur;
/**
* Creates a new instance of Account
*/
public Rate() {
}

@Override
public Integer getConversionId() {
    return conversionid;
}

public void setConversionId(Integer conversionid) {
    this.conversionid = conversionid;
}
@Override
public BigDecimal getValue() {
    return value;
}

public void setRate(double rate) {
    this.rate = rate;
}

public double getRate(String conversion) {
    return rate;
}

public String getFromCur() {
    return fromCur;
}

public void setFromCur(String from) {
    this.fromCur = from;
}

public String getToCur() {
    return toCur;
}

public void setToCur(String to) {
    this.toCur = to;
}

}

【问题讨论】:

  • 如果你得到这个异常,它只是意味着你正在寻找的行不存在。也许您正在查询不同的表或架构。或者您可能没有提交对数据库所做的更改。
  • 问题不在于数据库,我正确配置了所有内容,您可以看到屏幕截图的第一行有一个 fromcurrency BRA 和 to currency EUR 的表。我的问题是从角色获取数据并将其放入实体对象(Rate)中以将其用作方法中的值。我使用的 JPQL 查询不正确,我很难理解要使用哪种查询和实体管理器方法。
  • 您没有发布实体的代码,因此很难找到那里的错误。您还将参数传递给您的查询,尽管它没有任何参数。但是如果查询无效,你会得到另一个异常。您得到的异常清楚地表明查询已执行但未返回任何内容。
  • 代码必须在问题本身中。不在github上。

标签: java jpa jpql


【解决方案1】:

试图查看代码中是否存在导致问题的小问题,但没有找到。

这是我测试的方法,并附有一些注释和调试代码以提供帮助。

// changed input amount to big decimal to avoid floating point issues
public BigDecimal convertTo(String from, String to, BigDecimal value) {

    // changed to validate the currency code - note BRA will fail - need to change to BRL - remove this code if you dont need it.
    Currency fromCurr = Currency.getInstance(from);
    Currency toCurr = Currency.getInstance(to);

    // debugging code - to help troubleshoot (only use this on small table) - will print out the contents of the table so you can see if data is not correct
    List<Rate> rates = em.createQuery("SELECT c FROM Rate c", Rate.class).getResultList();
    if (rates == null || rates.isEmpty()) {
        throw new RuntimeException("rates table is empty");
    }

    for (Rate r : rates) {
        // push to sysout or whatever logger you are using
        System.out.println(String.format("Rate:fromCur[%s], toCur[%s]", r.getFromCur(), r.getToCur()));
    }
    // end debugging code - remove when no longer needed.

    // changed the query to use bind parameters - :fromCurrency, :toCurrency
    TypedQuery<Rate> query = em.createQuery(
            "SELECT c FROM Rate c WHERE c.fromCur = :fromCurrency AND c.toCur = :toCurrency", Rate.class);

    query.setParameter("fromCurrency", fromCurr.getCurrencyCode());
    query.setParameter("toCurrency", toCurr.getCurrencyCode());

    Rate rate = query.getSingleResult();
    if (rate == null) {
        throw new EntityNotFoundException("Can't find rate");
    }

    // changed to use big decimal, scale and rounding as well as avoid floating point issues
    BigDecimal converted =
            value.multiply(rate.getValue()).setScale(toCurr.getDefaultFractionDigits(), RoundingMode.HALF_DOWN);

    return converted;
}

我包含了一些关于处理货币的说明,以帮助您避免潜在的陷阱。希望这可以帮助您继续前进

【讨论】:

  • 感谢@Bob Lukens 的帮助,我更新将表中的 BRA 更改为 BRL。我尝试了您的测试,并且不再出现任何错误,这很好。但是它从调试代码List&lt;Rate&gt; rates = em.createQuery("SELECT c FROM Rate c", Rate.class).getResultList(); 返回“费率表为空”我怀疑实体费率没有正确实现。它在 NetBeans 中构建并且不发出警告,但逻辑一定是错误的。这是 Rate.java 代码的链接 [链接] (github.com/teowey/currency-converter/blob/master/src/java/…)
  • 代码看起来是正确的,否则在与实体管理器交互时会出现很多不同的异常。
  • 这可能是您在 persistence.xml 中的问题:&lt;property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/&gt; - 这是告诉 JPA 每次使用实体中的信息删除并重新创建数据库。因此,如果您的表中有数据或曾经有数据,则每次启动应用程序时,它都可能将其全部删除
  • 是的,我改成 value="create",还是不行。我编写了一个方法 viewRates() 来输出所有费率,但它不起作用。在 Netbeans 中,如果您右键单击 persistence.xml,您可以选择“运行 JPQL 查询”。它允许您访问数据库。所以我测试了SELECT c FROM Rate c,它可以工作并显示所有数据库行。我想在 web (index.xhtml) 和 src (currencyManager.java 等) 之间存在一些问题。
  • 我发现了问题:更改了 faces-config.xml 文件。它丢失了&lt;if&gt;#{!currencyManager.getSuccess()}&lt;/if&gt;。 index.xhtml 和 error.xhtml 标签内的 EL 错误。
【解决方案2】:

使用 JPQL 从数据库中检索行数据或表数据 只需要实现JPQl Query。我这样做很简单。这里我的表名是农夫,类名是农夫,我使用注释作为数据库。

public static void main(String[] args) {
    EntityManager entityMgr = getEntityManager();
    entityMgr.getTransaction().begin();
    Query q = entityMgr.createQuery("SELECT s FROM Farmer s");

    List<Farmer> list = q.getResultList();
    for(Farmer s:list) {
         System.out.println("Id : "+s.getId()+" Farmer NAME : "+s.getName()+" location : "+s.getVillage());
      }
    entityMgr.getTransaction().commit();
    entityMgr.clear();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-29
    • 1970-01-01
    • 2019-11-19
    • 2017-06-29
    • 2012-12-18
    相关资源
    最近更新 更多