目前我正在学习Hibernate,因此我使用以下三种方式在MySQL中创建数据库(MWE)
create database `fakturowanie`;
use `fakturowanie`;
drop table if exists `wykupione_uslugi`; #table 'bought services'
drop table if exists `uslugi`; #table 'services'
drop table if exists `kontrahenci`; table 'contractors'
create table `kontrahenci`(
`kontrahent_id` int unsigned auto_increment primary key,
`nazwisko` varchar(80), #surname
`imie` varchar(30), #name
`firma_nazwa` varchar(100), #company name
`nip_pesel` varchar(20) not null unique, #person ID
`ulica_nr_mieszkania` varchar(100), #street
`kod_pocztowy` varchar(6), #postal code
`miejscowosc` varchar(30), #city
`sposob_zaplaty` varchar(7) not null default 'gotówka', #payment method default cash
`uwzglednij_numer_faktury` bool not null default true, #include invoice number
`alias` varchar(30) not null
)engine = InnoDB
default charset = utf8
collate = utf8_polish_ci;
create table `uslugi`(
`usluga_id` int unsigned auto_increment primary key,
`nazwa` varchar(80) not null, #name
`symbol_PKWIU/PKOB` varchar(10),
`jednostka` varchar(10) not null, #unit
`cena_jednostkowa_netto` decimal(6, 2) not null, #unit price
`stawka_vat` int(2) unsigned not null #tax rate
)engine = InnoDB
default charset = utf8
collate = utf8_polish_ci;
create table `wykupione_uslugi`(
`id` int unsigned auto_increment primary key,
`kontrahent_id` int unsigned not null,
`usluga_id` int unsigned not null,
foreign key(kontrahent_id) references kontrahenci(kontrahent_id),
foreign key(usluga_id) references uslugi(usluga_id)
)engine = InnoDB
default charset = utf8
collate = utf8_polish_ci;
insert into `kontrahenci` (
nazwisko, imie, firma_nazwa, nip_pesel, ulica_nr_mieszkania, kod_pocztowy, miejscowosc, sposob_zaplaty, uwzglednij_numer_faktury, alias)
values ('Best', 'John', 'Best Inc.', 111-111-111, 'Best Street 5', 11-111, 'Best Valley', 'cash', 1, 'test');
insert into `uslugi` (
nazwa, jednostka, cena_jednostkowa_netto, stawka_vat)
values (
'Best tutoring', 'hour', 1000.00, 0);
insert into `wykupione_uslugi` (kontrahent_id, usluga_id) values (1, 1);
我尝试使用Hibernate做的事情等同于这个SQL查询
select
`uslugi`.`nazwa`,
`uslugi`.`symbol_PKWIU/PKOB`,
`uslugi`.`jednostka`,
`uslugi`.`cena_jednostkowa_netto`,
`uslugi`.`stawka_vat`
from
`wykupione_uslugi`
left join `kontrahenci` on `wykupione_uslugi`.`kontrahent_id` = `kontrahenci`.`kontrahent_id`
left join `uslugi` on `wykupione_uslugi`.`usluga_id` = `uslugi`.`usluga_id`
where
`kontrahenci`.`alias` = 'test';
我创建了这样的映射类:
Service
类
@Entity
@Table(name="uslugi", schema = "fakturowanie")
public class Service
{
private int serviceID;
private String serviceName;
private String symbol;
private String unit;
private BigDecimal unitPrice;
private int tax;
private Collection<ServicesList> servicesLists;
@Id
@Column(name = "usluga_id", nullable = false)
@GeneratedValue(generator="increment")
@GenericGenerator(name="increment", strategy = "increment")
public int getServiceID()
{
return serviceID;
}
public void setServiceID(int serviceID)
{
this.serviceID = serviceID;
}
@Basic
@Column(name = "nazwa", nullable = false, length = 80)
public String getServiceName()
{
return serviceName;
}
public void setServiceName(String serviceName)
{
this.serviceName = serviceName;
}
@Basic
@Column(name = "symbol_PKWIU/PKOB", nullable = false, length = 10)
public String getSymbol()
{
return symbol;
}
public void setSymbol(String symbol)
{
this.symbol = symbol;
}
@Basic
@Column(name = "jednostka", nullable = false, length = 10)
public String getUnit()
{
return unit;
}
public void setUnit(String unit)
{
this.unit = unit;
}
@Basic
@Column(name = "cena_jednostkowa_netto", nullable = false, precision = 2)
public BigDecimal getUnitPrice()
{
return unitPrice;
}
public void setUnitPrice(BigDecimal unitPrice)
{
this.unitPrice = unitPrice;
}
@Basic
@Column(name = "stawka_vat", nullable = false)
public int getTax()
{
return tax;
}
public void setTax(int tax)
{
this.tax = tax;
}
@OneToMany(mappedBy = "servicesMapping")
public Collection<ServicesList> getServicesLists()
{
return servicesLists;
}
public void setServicesLists(Collection<ServicesList> servicesLists)
{
this.servicesLists = servicesLists;
}
}
Contractor
上课
@Entity
@Table(name = "kontrahenci", schema = "fakturowanie")
public class Contractor
{
private int contractorID;
private String surname;
private String name;
private String companyName;
private String taxpayerINum;
private String street;
private String postalCode;
private String city;
private PaymentMethod paymentMethod;
private byte includeInvoiceNum;
private String alias;
private Collection<ServicesList> servicesList;
@Id
@Column(name = "kontrahent_id", nullable = false)
@GeneratedValue(generator="increment")
@GenericGenerator(name="increment", strategy = "increment")
public int getContractorID()
{
return contractorID;
}
public void setContractorID(int contractorID)
{
this.contractorID = contractorID;
}
@Basic
@Column(name = "nazwisko", nullable = true, length = 80)
public String getSurname()
{
return surname;
}
public void setSurname(String surname)
{
this.surname = surname;
}
@Basic
@Column(name = "imie", nullable = true, length = 30)
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
@Basic
@Column(name = "firma_nazwa", nullable = true, length = 100)
public String getCompanyName()
{
return companyName;
}
public void setCompanyName(String companyName)
{
this.companyName = companyName;
}
@Basic
@Column(name = "nip_pesel", unique = true, length = 20, nullable = false)
public String getTaxpayerINum()
{
return taxpayerINum;
}
public void setTaxpayerINum(String taxpayerINum)
{
this.taxpayerINum = taxpayerINum;
}
@Basic
@Column(name = "ulica_nr_mieszkania", nullable = true, length = 100)
public String getStreet()
{
return street;
}
public void setStreet(String street)
{
this.street = street;
}
@Basic
@Column(name = "kod_pocztowy", nullable = true, length = 6)
public String getPostalCode()
{
return postalCode;
}
public void setPostalCode(String postalCode)
{
this.postalCode = postalCode;
}
@Basic
@Column(name = "miejscowosc", nullable = true, length = 30)
public String getCity()
{
return city;
}
public void setCity(String city)
{
this.city = city;
}
@Enumerated(EnumType.STRING)
@Column(name = "sposob_zaplaty", nullable = false, length = 7)
public PaymentMethod getPaymentMethod()
{
return paymentMethod;
}
public void setPaymentMethod(PaymentMethod paymentMethod)
{
this.paymentMethod = paymentMethod;
}
@Basic
@Column(name = "uwzglednij_numer_faktury", nullable = false)
public byte getIncludeInvoiceNum()
{
return includeInvoiceNum;
}
public void setIncludeInvoiceNum(byte includeInvoiceNum)
{
this.includeInvoiceNum = includeInvoiceNum;
}
@Basic
@Column(name = "alias", nullable = false, length = 30)
public String getAlias()
{
return alias;
}
public void setAlias(String alias)
{
this.alias = alias;
}
@OneToMany(mappedBy = "contractorMapping")
public Collection<ServicesList> getServicesList()
{
return servicesList;
}
public void setServicesList(Collection<ServicesList> servicesList)
{
this.servicesList = servicesList;
}
}
ServicesList
上课
@Entity
@Table(name = "wykupione_uslugi", schema = "fakturowanie")
public class ServicesList
{
private int id;
private int contractorID;
private int serviceID;
private Contractor contractorMapping;
private Service servicesMapping;
@Id
@Column(name = "id", nullable = false)
@GeneratedValue(generator="increment")
@GenericGenerator(name="increment", strategy = "increment")
public int getId()
{
return id;
}
public void setId(int id) {
this.id = id;
}
@Basic
@Column(name = "kontrahent_id", nullable = false)
public int getContractorID() {
return contractorID;
}
public void setContractorID(int contractorID) {
this.contractorID = contractorID;
}
@Basic
@Column(name = "usluga_id", nullable = false)
public int getServiceID() {
return serviceID;
}
public void setServiceID(int serviceID) {
this.serviceID = serviceID;
}
@ManyToOne
@JoinColumn(name = "kontrahent_id", referencedColumnName = "kontrahent_id", insertable = false, updatable = false)
public Contractor getContractorMapping() {
return contractorMapping;
}
public void setContractorMapping(Contractor contractorMapping) {
this.contractorMapping = contractorMapping;
}
@ManyToOne
@JoinColumn(name = "usluga_id", referencedColumnName = "usluga_id", insertable = false, updatable = false)
public Service getServicesMapping() {
return servicesMapping;
}
public void setServicesMapping(Service servicesMapping) {
this.servicesMapping = servicesMapping;
}
}
我还创建了HibernateUtil
类来处理SessionFactory
public class HibernateUtil
{
private static final SessionFactory sessionFactory = buildSessionFactory();
private static SessionFactory buildSessionFactory() {
try {
Configuration configuration = new Configuration();
configuration.configure();
StandardServiceRegistry standardRegistry = new StandardServiceRegistryBuilder()
.configure()
.build();
return configuration.buildSessionFactory(standardRegistry);
}
catch(Exception e) {
throw new ExceptionInInitializerError(e);
}
}
public static Session getSession()
{
return sessionFactory.openSession();
}
public static void close()
{
sessionFactory.close();
}
}
Main
类看起来像这样:
public class Main
{
public static void main(String[] args)
{
Session session = HibernateUtil.getSession();
session.beginTransaction();
List<Service> services = session.createQuery(
"select Service.serviceName, Service.symbol, Service.unit, Service.unitPrice, Service.tax " +
"from ServicesList " +
"left join ServicesList.contractorMapping left join ServicesList.servicesMapping " +
"where Contractor.alias = 'test'").list();
for(Service s : services)
{
System.out.println(s.getServiceID() + "\t" + s.getServiceName() + "\t" + s.getSymbol() + "\t" + s.getUnit() +
"\t" + s.getUnitPrice() + "\t" + s.getTax());
}
session.getTransaction().commit();
session.close();
}
}
但是错误说查询有问题,我真的不知道哪些是错的
Exception in thread "main" java.lang.NullPointerException
at java.lang.String$CaseInsensitiveComparator.compare(String.java:1192)
at java.lang.String$CaseInsensitiveComparator.compare(String.java:1186)
at java.util.TreeMap.getEntryUsingComparator(TreeMap.java:376)
at java.util.TreeMap.getEntry(TreeMap.java:345)
at java.util.TreeMap.get(TreeMap.java:278)
at org.hibernate.dialect.function.SQLFunctionRegistry.findSQLFunction(SQLFunctionRegistry.java:45)
at org.hibernate.hql.internal.ast.util.SessionFactoryHelper.findSQLFunction(SessionFactoryHelper.java:369)
at org.hibernate.hql.internal.ast.tree.IdentNode.getDataType(IdentNode.java:374)
at org.hibernate.hql.internal.ast.HqlSqlWalker.lookupProperty(HqlSqlWalker.java:652)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.propertyRef(HqlSqlBaseWalker.java:1140)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.joinElement(HqlSqlBaseWalker.java:3838)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromElement(HqlSqlBaseWalker.java:3701)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromElementList(HqlSqlBaseWalker.java:3579)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromClause(HqlSqlBaseWalker.java:718)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:574)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:311)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:259)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:261)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:189)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:141)
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:115)
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:77)
at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:153)
at org.hibernate.internal.AbstractSharedSessionContract.getQueryPlan(AbstractSharedSessionContract.java:545)
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:654)
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:102)
at Main.main(Main.java:12)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
修改
Maciej Kowalski的回答有所帮助,但我仍然得到了一些奇怪的和不需要的输出,顺便说一下主要没有退出(正如它应该的那样),而是“悬挂”#。我高举黄色正确的输出。
答案 0 :(得分:2)
这里有一些事情......
首先,您正在尝试进行投影(如果您想处理返回的数据,但不更新它,这是一件好事),并希望获得实体列表。不这样做。
第二次,您以错误的方式引用列。标准是使用别名并从那里继续(更容易阅读和维护)。
所以,考虑到这些,我会:
1)为投影创建一个特殊的结果类,以便更容易使用该查询。它还可以节省大量的锅炉板代码解析:
package com.mypkg;
public class ServiceResult{
private String serviceName;
private String symbol;
private String unit;
private BigDecimal unitPrice;
private int tax;
public ServiceResult(String serviceName, String symbol
,String unit, BigDecimal unitPrice, int tax){
// set the field values
}
}
2)将查询更改为以下内容:
List<ServiceResult> services = session.createQuery(
"select new com.mypkg.ServiceResult(service.serviceName
,service.symbol, service.unit
, service.unitPrice, service.tax) " +
"from ServicesList serviceList" +
" left join serviceList.contractorMapping contractor" +
" left join serviceList.servicesMapping service" +
"where contractor.alias = 'test'")
.list();
3)如果您打算真正获得整个服务实体,请使用此查询:
List<Service> services = session.createQuery(
"select service " +
"from Service service" +
" left join service.servicesLists servicesLists" +
" left join servicesLists.contractorMapping contractor" +
"where contractor.alias = 'test'")
.list();
侧面
由于此处有一些连接,因此您可能需要添加distinct以不获得冗余结果。