Bre*_*ett 4 java sql hibernate
我有一个Java应用程序,它通过Hibernate与MySQL连接.
在我的代码中,我让应用程序执行SQL命令:
final SQLQuery query = sf.getCurrentSession().createSQLQuery(
"select\n" +
" id, null as store_id, case when transaction_type = 'SALE' then 1 else -1 end as sign, payment_type,\n" +
" sum(cost_before_tax) as amount_before_tax, sum(tax_amount) as tax_amount, sum(cost) as amount,\n" +
" sum(ticket_count) as count\n" +
"from settlement_collection_initial_settlement\n" +
"where\n" +
" business_date between :start and :end\n" +
(storeID != null ? " and store_id = :store\n" : "") +
"group by transaction_type, payment_type"
);
query.addEntity(AmountRow.class);
query.setDate("start", start);
query.setDate("end", end != null ? end : start);
if (storeID != null) {
query.setString("store", new UUIDType().toSQLString(storeID));
}
return query.list();
Run Code Online (Sandbox Code Playgroud)
但是,如果我在MySqlWorkbench中运行完全相同的查询:
select
id, store_id, case when transaction_type = 'SALE' then 1 else -1 end as sign, payment_type,
sum(cost_before_tax) as amount_before_tax, sum(tax_amount) as tax_amount, sum(cost) as amount,
sum(ticket_count) as count
from settlement_collection_initial_settlement
where
business_date between '2018-07-27' and '2018-07-27'
and store_id = 'xxxxxx'
group by transaction_type, payment_type
Run Code Online (Sandbox Code Playgroud)
请注意,这些结果很接近,但不一样.看看这两CASH行,直接SQL显示第二CASH行,其中包含不同的sign值和其他值.所以在essense中,Hibernate执行的sql正在重复那个CASH行.
对我来说,看起来两种方式都应该返回完全相同的结果. 有谁知道为什么我的Hibernate SQL从直接执行SQL时返回不同(错误)的结果?
更新:
这是我的AmountRow班级:
@Entity
public class AmountRow {
static final int SIGN_SALE_OR_DEBIT = 1, SIGN_REFUND_OR_CREDIT = -1;
@Id
private float id;
@ManyToOne
@JoinColumn(name = "store_id", nullable = true)
private Store store;
@Column(nullable = true)
@Enumerated(EnumType.STRING)
private Payment.Type paymentType;
private int sign;
// NOTE: "$" is the name of a custom class
@Column(nullable = false)
@org.hibernate.annotations.Type(type = "com.mycompany.service.$Type")
private $ amountBeforeTax, taxAmount, amount;
@Column(nullable = false)
private int count;
// Hibernate constructor
protected AmountRow() {}
// NOTE: "$" is the name of a custom class
AmountRow(final $ amountBeforeTax, final $ taxAmount, final $ amount, final int count, final int sign) {
Assert.noneNull(amountBeforeTax, "amountBeforeTax", taxAmount, "taxAmount", amount, "amount");
Assert.notNegative(count, "count");
assertValidSign(sign);
this.amountBeforeTax = amountBeforeTax;
this.taxAmount = taxAmount;
this.amount = amount;
this.count = count;
this.sign = sign;
}
// NOTE: "$" is the name of a custom class
AmountRow(final $ amountBeforeTax, final $ taxAmount, final $ amount, final int count, final int sign, final Payment.Type paymentType) {
this(amountBeforeTax, taxAmount, amount, count, sign);
this.paymentType = paymentType;
}
static void assertValidSign(final int sign) {
if (sign != SIGN_SALE_OR_DEBIT && sign != SIGN_REFUND_OR_CREDIT)
throw new IllegalArgumentException("invalid sign " + sign);
}
public String toString() {
return "AmountRow[paymentType=" + paymentType + ", sign=" + sign + ", amountBeforeTax=" + amountBeforeTax + ", taxAmount=" + taxAmount + ", amount=" + amount + ", count=" + count + "]";
}
public Store getStore() {
return store;
}
public Payment.Type getPaymentType() {
return paymentType;
}
public int getSign() {
return sign;
}
public $ getAmountBeforeTax() {
return amountBeforeTax;
}
public $ getTaxAmount() {
return taxAmount;
}
public $ getAmount() {
return amount;
}
public int getCount() {
return count;
}
public $ getAmountBeforeTaxPerCount() {
return count != 0 ? amountBeforeTax.divide(count) : null;
}
public $ getAmountPerCount() {
return count != 0 ? amount.divide(count) : null;
}
}
Run Code Online (Sandbox Code Playgroud)
这是由应用程序和数据库之间的不同时区引起的.
或者:
您的HSQL还会在代码中暴露出另一个问题:结果重复.
您应该发布AmountRow课程进一步调查.
更新
读完AmountRow课后,问题是使用float @Id键会导致错误的等式检查,使Hibernate无法从DB加载数据.你永远不应该依赖浮动/双重平等.
@ df778899对此问题有很好的解释.
将@Id字段更改为long/int以解决重复问题.