简体   繁体   English

MySQL Hibernate中的空指针异常HQL

[英]Null pointer exception HQL in MySQL Hibernate

Currently I'm learning Hibernate and so I created database in MySQL with three tables in following way (MWE) 目前,我正在学习Hibernate,因此我以以下方式(MWE)在MySQL中用三个表创建了数据库

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

What I'm trying to do using Hibernate is equivalent of this SQL query 我要使用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';

I created mapped classes like this: 我创建了这样的映射类:
Service class 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 class 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 class 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;
}
}

I also created HibernateUtil class to handle SessionFactory 我还创建了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();
}
}

And Main class looks like this: Main class看起来像这样:

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

but the error says that's something wrong with query and I don't really know what can be wrong 但是错误表明查询有问题,我真的不知道有什么问题

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)  

EDIT 编辑
Answer by Maciej Kowalski helped but still I'm getting some weird and unwanted output, btw main does not exit (as it supposed to) but is 'hanging'. Maciej Kowalski的回答有所帮助,但我仍然得到一些奇怪和不需要的输出,btw main并没有退出(如预期的那样)而是“挂起”。 I highlited yellow correct output. 我将黄色正确输出高亮显示。 在此处输入图片说明

There are a few things here.. 这里有几件事。

First , you are trying to make projection (which is a good thing if you want to work on the returned data, but not update it) and expecting to get a List of entities. 首先 ,您正在尝试进行投影(如果您要处理返回的数据但不更新它,这是一件好事),并期望获得实体列表。 Does not work that way. 不能那样工作。

Second , you are referencing the columns in a wrong way. 其次 ,您以错误的方式引用列。 The standard is to use an alias and go on from there (so much easier to read and maintain). 标准是使用别名并从那里继续(这样更易于阅读和维护)。

So, having those in mind i would: 因此,考虑到这些,我会:

1) Create a special result class for the projection, so that it would be easier to work with that query. 1)为投影创建一个特殊的结果类,以便更轻松地使用该查询。 It will also save you tons of boiler plate code parsing: 它还将为您节省大量的锅炉板代码解析:

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) Change the query to the following: 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) IF your intention was to actually get the whole Service entities, then use this query: 3)如果您的意图是实际获得整个Service实体,然后使用此查询:

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

On the side 在一边

As there are a few joins going on here, so you might need to add distinct to not get redundant results. 由于此处正在进行一些连接,因此您可能需要添加distinct,以免获得多余的结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM