加入 table 列。怎么可能?
Join table with column. How is possible?
任何了解此类查询的人:
@Entity
@Table(name="ACCOUNT")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@NamedQueries({
@NamedQuery(name = Account.GET_EXPIRATION_DATE, query="SELECT account.expirationDate FROM " +
"Domain domain JOIN domain.account WHERE domain.id = :domainId"),
@NamedQuery(name = Account.GET_BALANCE, query="SELECT account.balance FROM " +
"Domain domain JOIN domain.account WHERE domain.id = :domainId")
})
我不明白这是什么 "Domain domain JOIN domain.account" 我们可以将一个 table 与另一个连接,但它接缝我们将 table 与列 .. 连接起来?
这些是相关的 类:
package com.smsoffice.admin;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import static javax.persistence.CascadeType.*;
import com.smsoffice.billing.Account;
import com.smsoffice.billing.PrepaidAccount;
@Entity
@Table(name="DOMAIN")
@NamedQueries({
@NamedQuery(name=Domain.GET_ALL_DOMAINS, query="SELECT d FROM Domain d ORDER BY d.name"),
@NamedQuery(name=Domain.GET_ACCOUNT, query="SELECT d.account FROM Domain d WHERE d.id = :id"),
@NamedQuery(name=Domain.GET_DOMAIN_BY_STATUS, query="SELECT d FROM Domain d WHERE d.enabled = :enabled ORDER BY d.name"),
@NamedQuery(name=Domain.GET_DOMAIN_BY_NAME, query="SELECT d FROM Domain d WHERE d.name = :name")
})
public class Domain implements Serializable {
private static final long serialVersionUID = 1L;
public final static String GET_ALL_DOMAINS = "Domain.getAllDomains";
public final static String GET_ACCOUNT = "Domain.getAccount";
public final static String GET_DOMAIN_BY_STATUS = "Domain.getAllDomainsByStatus";
public final static String GET_DOMAIN_BY_NAME = "Domain.getDomainByName";
public final static transient Domain ROOT = new Domain("ROOT");
public static Domain SYSTEM_DOMAIN = new Domain("SYSTEM");
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
@Column(unique = true, length = 96)
private String name;
//unique id of the service - one per domain
@GeneratedValue(strategy = GenerationType.AUTO)
private int serviceId;
//indicates whether the domain is enabled
private Boolean enabled = true;
//short code for the domain sms events
private int shortCode;
//prefix for parsing
private String prefix;
private String clientPrefix = "";
//bank account
@OneToOne(cascade = {PERSIST, REFRESH, REMOVE})
private Account account = new PrepaidAccount();
@OneToMany
private Set<User> users = new HashSet<User>();
public Domain() {}
public Domain(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getServiceId() {
return serviceId;
}
public void setServiceId(int serviceId) {
this.serviceId = serviceId;
}
public int getShortCode() {
return shortCode;
}
public void setShortCode(int shortCode) {
this.shortCode = shortCode;
}
public String getPrefix() {
return prefix;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
}
public Set<User> getUsers() {
return users;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Domain)) {
return false;
}
Domain domain = (Domain) obj;
return getName().toUpperCase().equals(domain.getName().toUpperCase());
}
@Override
public int hashCode() {
return getName().toUpperCase().hashCode();
}
@Override
public String toString() {
return "[" + name + "("+ account + ")]";
}
public int getId() {
return id;
}
public void setClientPrefix(String clientPrefix) {
this.clientPrefix = clientPrefix != null ? clientPrefix : "";
}
public String getClientPrefix() {
return clientPrefix;
}
}
还有这个:
package com.smsoffice.billing;
import static javax.persistence.CascadeType.ALL;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.Calendar;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToOne;
import javax.persistence.Table;
@Entity
@Table(name="ACCOUNT")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@NamedQueries({
@NamedQuery(name = Account.GET_EXPIRATION_DATE, query="SELECT account.expirationDate FROM " +
"Domain domain JOIN domain.account account WHERE domain.id = :domainId"),
@NamedQuery(name = Account.GET_BALANCE, query="SELECT account.balance FROM " +
"Domain domain JOIN domain.account account WHERE domain.id = :domainId")
})
public abstract class Account {
public static final MathContext MATH_CONTEXT = new MathContext(9, RoundingMode.HALF_UP);
public static final int SCALE = 3;
public static final int PRECISION = 9;
public static final String GET_BALANCE = "Account.getBalance";
public static final String GET_EXPIRATION_DATE = "Account.getExpirationDate";
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
@Column(precision = PRECISION, scale = SCALE)
protected BigDecimal balance = BigDecimal.ZERO;
@OneToOne(cascade = ALL)
protected Tariff tariff;
private Date activationDate = new Date();
private Date expirationDate;
public Account() {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.MONTH, 1);
setExpirationDate(calendar.getTime());
}
public BigDecimal getBalance() {
return balance;
}
public Tariff getTariff() {
return tariff;
}
public void setTariff(Tariff tariff) {
this.tariff = tariff;
}
void deposit(BigDecimal amount) {
balance = balance.add(amount).setScale(SCALE, MATH_CONTEXT.getRoundingMode());
}
abstract boolean hasCredit(int eventCount);
abstract void makePayment(int eventCount) throws PaymentException;
public int getId() {
return id;
}
public Date getActivationDate() {
return activationDate;
}
public void setActivationDate(Date activationDate) {
this.activationDate = normalizeActivationDate(activationDate);
}
void setExpirationDate(Date expirationDate) {
this.expirationDate = normalizeExpirationDate(expirationDate);
}
public Date getExpirationDate() {
return expirationDate;
}
public boolean isExpired() {
Date now = new Date();
return now.after(expirationDate);
}
@Override
public String toString() {
return "[balance: " + balance + "; tariff: " + (tariff != null ? tariff.getPrice() : "no tariff") + "; expiration date: " + expirationDate.toString() + "]";
}
public void setBalance(BigDecimal newBalance) {
this.balance = newBalance;
}
private static final Date normalizeActivationDate(Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
return cal.getTime();
}
private static final Date normalizeExpirationDate(Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.set(Calendar.HOUR_OF_DAY, 23);
cal.set(Calendar.MINUTE, 59);
cal.set(Calendar.SECOND, 59);
cal.set(Calendar.MILLISECOND, 0);
return cal.getTime();
}
}
好吧,这些并不是真正的 SQL 查询,而是 JPQL 查询 - 有一个很好的 tutorial 描述,以及非常好的示例。请注意,在 JPQL 中,您不直接使用 tables,而是使用域模型的实体。
但是对于你的问题,让我们以这个查询为例:
SELECT account.balance FROM Domain domain JOIN domain.account WHERE domain.id = :domainId
SELECT account.balance
将 return 加入给定域记录的帐户的 balance
属性值
FROM Domain domain
表示 Domain
实体将用于查询来自相关 table 的数据,在 Domain
实体上使用 @Table(name="DOMAIN")
定义;小写 domain
只是在此查询中使用的别名(参见例如查询的 WHERE 部分)
JOIN domain.account
将与 Domain
实体的 account
字段上定义的注解 @OneToOne(cascade = {PERSIST, REFRESH, REMOVE})
一起使用,从 [=54= 中获取相关记录]由Account
个实体 代表
WHERE domain.id = :domainId
会将结果限制为 return 只有 Domain
和给定的 id
,以及它的 account
; :domainId
部分是 "query parameter" 并且很可能在代码中的某处用实际值替换,使用 query.setParameter("domainId", someValue);
之类的代码
所以整个查询应该 return BigDecimal
类型的值(参见 Account
实体中定义的字段 balance
)。
任何了解此类查询的人:
@Entity
@Table(name="ACCOUNT")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@NamedQueries({
@NamedQuery(name = Account.GET_EXPIRATION_DATE, query="SELECT account.expirationDate FROM " +
"Domain domain JOIN domain.account WHERE domain.id = :domainId"),
@NamedQuery(name = Account.GET_BALANCE, query="SELECT account.balance FROM " +
"Domain domain JOIN domain.account WHERE domain.id = :domainId")
})
我不明白这是什么 "Domain domain JOIN domain.account" 我们可以将一个 table 与另一个连接,但它接缝我们将 table 与列 .. 连接起来?
这些是相关的 类:
package com.smsoffice.admin;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import static javax.persistence.CascadeType.*;
import com.smsoffice.billing.Account;
import com.smsoffice.billing.PrepaidAccount;
@Entity
@Table(name="DOMAIN")
@NamedQueries({
@NamedQuery(name=Domain.GET_ALL_DOMAINS, query="SELECT d FROM Domain d ORDER BY d.name"),
@NamedQuery(name=Domain.GET_ACCOUNT, query="SELECT d.account FROM Domain d WHERE d.id = :id"),
@NamedQuery(name=Domain.GET_DOMAIN_BY_STATUS, query="SELECT d FROM Domain d WHERE d.enabled = :enabled ORDER BY d.name"),
@NamedQuery(name=Domain.GET_DOMAIN_BY_NAME, query="SELECT d FROM Domain d WHERE d.name = :name")
})
public class Domain implements Serializable {
private static final long serialVersionUID = 1L;
public final static String GET_ALL_DOMAINS = "Domain.getAllDomains";
public final static String GET_ACCOUNT = "Domain.getAccount";
public final static String GET_DOMAIN_BY_STATUS = "Domain.getAllDomainsByStatus";
public final static String GET_DOMAIN_BY_NAME = "Domain.getDomainByName";
public final static transient Domain ROOT = new Domain("ROOT");
public static Domain SYSTEM_DOMAIN = new Domain("SYSTEM");
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
@Column(unique = true, length = 96)
private String name;
//unique id of the service - one per domain
@GeneratedValue(strategy = GenerationType.AUTO)
private int serviceId;
//indicates whether the domain is enabled
private Boolean enabled = true;
//short code for the domain sms events
private int shortCode;
//prefix for parsing
private String prefix;
private String clientPrefix = "";
//bank account
@OneToOne(cascade = {PERSIST, REFRESH, REMOVE})
private Account account = new PrepaidAccount();
@OneToMany
private Set<User> users = new HashSet<User>();
public Domain() {}
public Domain(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getServiceId() {
return serviceId;
}
public void setServiceId(int serviceId) {
this.serviceId = serviceId;
}
public int getShortCode() {
return shortCode;
}
public void setShortCode(int shortCode) {
this.shortCode = shortCode;
}
public String getPrefix() {
return prefix;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
}
public Set<User> getUsers() {
return users;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Domain)) {
return false;
}
Domain domain = (Domain) obj;
return getName().toUpperCase().equals(domain.getName().toUpperCase());
}
@Override
public int hashCode() {
return getName().toUpperCase().hashCode();
}
@Override
public String toString() {
return "[" + name + "("+ account + ")]";
}
public int getId() {
return id;
}
public void setClientPrefix(String clientPrefix) {
this.clientPrefix = clientPrefix != null ? clientPrefix : "";
}
public String getClientPrefix() {
return clientPrefix;
}
}
还有这个:
package com.smsoffice.billing;
import static javax.persistence.CascadeType.ALL;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.Calendar;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToOne;
import javax.persistence.Table;
@Entity
@Table(name="ACCOUNT")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@NamedQueries({
@NamedQuery(name = Account.GET_EXPIRATION_DATE, query="SELECT account.expirationDate FROM " +
"Domain domain JOIN domain.account account WHERE domain.id = :domainId"),
@NamedQuery(name = Account.GET_BALANCE, query="SELECT account.balance FROM " +
"Domain domain JOIN domain.account account WHERE domain.id = :domainId")
})
public abstract class Account {
public static final MathContext MATH_CONTEXT = new MathContext(9, RoundingMode.HALF_UP);
public static final int SCALE = 3;
public static final int PRECISION = 9;
public static final String GET_BALANCE = "Account.getBalance";
public static final String GET_EXPIRATION_DATE = "Account.getExpirationDate";
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
@Column(precision = PRECISION, scale = SCALE)
protected BigDecimal balance = BigDecimal.ZERO;
@OneToOne(cascade = ALL)
protected Tariff tariff;
private Date activationDate = new Date();
private Date expirationDate;
public Account() {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.MONTH, 1);
setExpirationDate(calendar.getTime());
}
public BigDecimal getBalance() {
return balance;
}
public Tariff getTariff() {
return tariff;
}
public void setTariff(Tariff tariff) {
this.tariff = tariff;
}
void deposit(BigDecimal amount) {
balance = balance.add(amount).setScale(SCALE, MATH_CONTEXT.getRoundingMode());
}
abstract boolean hasCredit(int eventCount);
abstract void makePayment(int eventCount) throws PaymentException;
public int getId() {
return id;
}
public Date getActivationDate() {
return activationDate;
}
public void setActivationDate(Date activationDate) {
this.activationDate = normalizeActivationDate(activationDate);
}
void setExpirationDate(Date expirationDate) {
this.expirationDate = normalizeExpirationDate(expirationDate);
}
public Date getExpirationDate() {
return expirationDate;
}
public boolean isExpired() {
Date now = new Date();
return now.after(expirationDate);
}
@Override
public String toString() {
return "[balance: " + balance + "; tariff: " + (tariff != null ? tariff.getPrice() : "no tariff") + "; expiration date: " + expirationDate.toString() + "]";
}
public void setBalance(BigDecimal newBalance) {
this.balance = newBalance;
}
private static final Date normalizeActivationDate(Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
return cal.getTime();
}
private static final Date normalizeExpirationDate(Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.set(Calendar.HOUR_OF_DAY, 23);
cal.set(Calendar.MINUTE, 59);
cal.set(Calendar.SECOND, 59);
cal.set(Calendar.MILLISECOND, 0);
return cal.getTime();
}
}
好吧,这些并不是真正的 SQL 查询,而是 JPQL 查询 - 有一个很好的 tutorial 描述,以及非常好的示例。请注意,在 JPQL 中,您不直接使用 tables,而是使用域模型的实体。
但是对于你的问题,让我们以这个查询为例:
SELECT account.balance FROM Domain domain JOIN domain.account WHERE domain.id = :domainId
SELECT account.balance
将 return 加入给定域记录的帐户的balance
属性值FROM Domain domain
表示Domain
实体将用于查询来自相关 table 的数据,在Domain
实体上使用@Table(name="DOMAIN")
定义;小写domain
只是在此查询中使用的别名(参见例如查询的 WHERE 部分)JOIN domain.account
将与Domain
实体的account
字段上定义的注解@OneToOne(cascade = {PERSIST, REFRESH, REMOVE})
一起使用,从 [=54= 中获取相关记录]由Account
个实体 代表
WHERE domain.id = :domainId
会将结果限制为 return 只有Domain
和给定的id
,以及它的account
;:domainId
部分是 "query parameter" 并且很可能在代码中的某处用实际值替换,使用query.setParameter("domainId", someValue);
之类的代码
所以整个查询应该 return BigDecimal
类型的值(参见 Account
实体中定义的字段 balance
)。