gpt4 book ai didi

java - Hibernate:嵌入式 id 字段命名问题

转载 作者:行者123 更新时间:2023-11-30 08:08:59 26 4
gpt4 key购买 nike

我有一个实体CashFlow,它具有实体类CashFlowCategory的字段category。后者有一个由字段 nameusername 组成的复合键。在数据库中,这些字段称为 NAMEUSERNAME

该应用程序在 EclipseLink 下运行良好,但当我尝试切换到 Hibernate 时,遇到了此异常:

org.hibernate.HibernateException: Missing column: category_NAME in .APP.CASHFLOW

看起来 Hibernate(与 EclipseLink 不同)需要 category_ 前缀在 NAME 之前,即使我明确声明该列的命名应不带前缀:

@Column(name="NAME")
private String name;

如何告诉 Hibernate 查找“NAME”而不是“category_NAME”?

<小时/>

设置:

  • 玻璃鱼4.0
  • Derby 10.9.1.0

数据库结构:

现金流量表:

COLUMN_NAME         |TYPE_NAME|DEC&|NUM&|COLUM&|COLUMN_DEF|CHAR_OCTE&|IS_NULL&
------------------------------------------------------------------------------
ID |INTEGER |0 |10 |10 |NULL |NULL |NO
AMOUNT |DOUBLE |NULL|2 |52 |NULL |NULL |YES
DATE |DATE |0 |10 |10 |NULL |NULL |YES
DESCRIPTION |VARCHAR |NULL|NULL|255 |NULL |510 |YES
USERNAME |VARCHAR |NULL|NULL|255 |NULL |510 |YES
NAME |VARCHAR |NULL|NULL|255 |NULL |510 |YES
IDNUMBER |INTEGER |0 |10 |10 |NULL |NULL |YES

表现金流量类别

COLUMN_NAME         |TYPE_NAME|DEC&|NUM&|COLUM&|COLUMN_DEF|CHAR_OCTE&|IS_NULL&
------------------------------------------------------------------------------
TYPE |INTEGER |0 |10 |10 |NULL |NULL |YES
NAME |VARCHAR |NULL|NULL|255 |NULL |510 |NO
USERNAME |VARCHAR |NULL|NULL|255 |NULL |510 |NO
LIMIT |DOUBLE |NULL|2 |52 |NULL |NULL |YES
GOAL |DOUBLE |NULL|2 |52 |NULL |NULL |YES

实体:

现金流

package com.singularityfx.cashelyok.entities;

import java.time.LocalDate;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Transient;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import com.singularityfx.cashelyok.entities.enums.CashFlowType;

@Entity
public class CashFlow implements Comparable<CashFlow> {
@Id
@GeneratedValue
private int id;
@NotNull @Min(0)
private double amount;
@Size(max=200)
private String description;
@NotNull
private LocalDate date;
@OneToOne @NotNull
private CashFlowCategory category;
@Transient
private boolean editable = false;

public CashFlow() {}

public CashFlow(
LocalDate date,
CashFlowCategory category,
String description,
double amount) {
this.date = date;
this.category = category;
this.description = description;
this.amount = amount;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public CashFlowType getType() {
return category.getType();
}

public double getAmount() {
return amount;
}

public void setAmount(double amount) {
this.amount = amount;
}

public LocalDate getDate() {
return date;
}

public void setDate(LocalDate date) {
this.date = date;
}

public CashFlowCategory getCategory() {
return category;
}

public void setCategory(CashFlowCategory category) {
this.category = category;
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}

@Column(name="username")
public String getUsername() {
return category.getPrimaryKey().getUsername();
}

public boolean isEditable() {
return editable;
}

public void setEditable(boolean editable) {
this.editable = editable;
}

@Override
public String toString() {
return "(" + date + "|" + category + "|" + description
+ "|" + amount + "|" + category.getPrimaryKey().getUsername() + ")";
}

@Override
public int compareTo(CashFlow o) {
return this.getDate().compareTo(o.getDate());
}

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
long temp;
temp = Double.doubleToLongBits(amount);
result = prime * result + (int) (temp ^ (temp >>> 32));
result = prime * result
+ ((category == null) ? 0 : category.hashCode());
result = prime * result + ((date == null) ? 0 : date.hashCode());
result = prime * result
+ ((description == null) ? 0 : description.hashCode());
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
CashFlow other = (CashFlow) obj;
if (Double.doubleToLongBits(amount) != Double
.doubleToLongBits(other.amount))
return false;
if (category == null) {
if (other.category != null)
return false;
} else if (!category.equals(other.category))
return false;
if (date == null) {
if (other.date != null)
return false;
} else if (!date.equals(other.date))
return false;
if (description == null) {
if (other.description != null)
return false;
} else if (!description.equals(other.description))
return false;
return true;
}
}

现金流类别

package com.singularityfx.cashelyok.entities;

import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Transient;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;

import com.singularityfx.cashelyok.entities.enums.CashFlowType;

@Entity
public class CashFlowCategory implements Comparable<CashFlowCategory> {
@EmbeddedId
private CashFlowCategoryPK primaryKey;
@NotNull
private CashFlowType type;
@Min(0)
private double goal;
@Transient
public static final String SEPARATOR = " - ";

public CashFlowCategory() {}

public CashFlowCategory(String name, CashFlowType type, double goal, String username) {
this.primaryKey = new CashFlowCategoryPK(name, username);
this.type = type;
this.goal = goal;
}

@Override
public String toString() {
return type + SEPARATOR + primaryKey.getName();
}

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((primaryKey == null) ? 0 : primaryKey.hashCode());
result = prime * result + ((type == null) ? 0 : type.hashCode());
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
CashFlowCategory other = (CashFlowCategory) obj;
if (primaryKey == null) {
if (other.primaryKey != null)
return false;
} else if (!primaryKey.equals(other.primaryKey))
return false;
if (type != other.type)
return false;
return true;
}

@Override
public int compareTo(CashFlowCategory o) {
/*
* To avoid NullPointerException from javax.faces.component.UIInput.compareValues
* when adding new cash flow via cash flows page after attempting to add
* cash flow without filling all mandatory fields
*/
if (type == null) {
return -1;
}

int returnValue = type.compareTo(o.getType());
if (returnValue == 0) {
returnValue = primaryKey.getName().compareTo(o.getName());
}
return returnValue;
}

public CashFlowCategoryPK getPrimaryKey() {
return primaryKey;
}

public void setPrimaryKey(CashFlowCategoryPK primaryKey) {
this.primaryKey = primaryKey;
}

public String getName() {
return primaryKey.getName();
}

public CashFlowType getType() {
return type;
}

public String getUsername() {
return primaryKey.getUsername();
}

public double getGoal() {
return goal;
}

public void setGoal(double goal) {
this.goal = goal;
}
}

CashFlowCategoryPK(嵌入 ID)

package com.singularityfx.cashelyok.entities;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

@Embeddable
public class CashFlowCategoryPK implements Serializable {
private static final long serialVersionUID = 392533037882395947L;
@NotNull @Size(min=1, max=200)
@Column(name="NAME")
private String name;
@NotNull @Size(min=1, max=200)
@Column(name="USERNAME")
private String username;

public CashFlowCategoryPK() {
}

public CashFlowCategoryPK(String name, String username) {
this.name = name;
this.username = username;
}

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result
+ ((username == null) ? 0 : username.hashCode());
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
CashFlowCategoryPK other = (CashFlowCategoryPK) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (username == null) {
if (other.username != null)
return false;
} else if (!username.equals(other.username))
return false;
return true;

}
public String getName() {
return name;
}

public String getUsername() {
return username;
}
}

堆栈跟踪:

org.hibernate.HibernateException: Missing column: category_NAME in .APP.CASHFLOW
at org.hibernate.mapping.Table.validateColumns(Table.java:366)
at org.hibernate.cfg.Configuration.validateSchema(Configuration.java:1338)
at org.hibernate.tool.hbm2ddl.SchemaValidator.validate(SchemaValidator.java:175)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:525)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1859)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:857)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:850)
at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.withTccl(ClassLoaderServiceImpl.java:425)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:849)
at org.hibernate.jpa.HibernatePersistenceProvider.createContainerEntityManagerFactory(HibernatePersistenceProvider.java:152)
at org.glassfish.persistence.jpa.PersistenceUnitLoader.loadPU(PersistenceUnitLoader.java:199)
at org.glassfish.persistence.jpa.PersistenceUnitLoader.<init>(PersistenceUnitLoader.java:107)
at org.glassfish.persistence.jpa.JPADeployer$1.visitPUD(JPADeployer.java:223)
at org.glassfish.persistence.jpa.JPADeployer$PersistenceUnitDescriptorIterator.iteratePUDs(JPADeployer.java:510)
at org.glassfish.persistence.jpa.JPADeployer.createEMFs(JPADeployer.java:230)
at org.glassfish.persistence.jpa.JPADeployer.prepare(JPADeployer.java:168)
at com.sun.enterprise.v3.server.ApplicationLifecycle.prepareModule(ApplicationLifecycle.java:922)
at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:431)
at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:219)
at org.glassfish.deployment.admin.DeployCommand.execute(DeployCommand.java:491)
at com.sun.enterprise.v3.admin.CommandRunnerImpl$2$1.run(CommandRunnerImpl.java:527)
at com.sun.enterprise.v3.admin.CommandRunnerImpl$2$1.run(CommandRunnerImpl.java:523)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:360)
at com.sun.enterprise.v3.admin.CommandRunnerImpl$2.execute(CommandRunnerImpl.java:522)
at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:546)
at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:1423)
at com.sun.enterprise.v3.admin.CommandRunnerImpl.access$1500(CommandRunnerImpl.java:108)
at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1762)
at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1674)
at com.sun.enterprise.v3.admin.AdminAdapter.doCommand(AdminAdapter.java:534)
at com.sun.enterprise.v3.admin.AdminAdapter.onMissingResource(AdminAdapter.java:224)
at org.glassfish.grizzly.http.server.StaticHttpHandler.service(StaticHttpHandler.java:297)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:246)
at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:191)
at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:168)
at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:189)
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:838)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:113)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:55)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:564)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:544)
at java.lang.Thread.run(Thread.java:745)]]

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="cashelyok" transaction-type="JTA">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<jta-data-source>cashelyok-resource</jta-data-source>
<properties>
<property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.SunOneJtaPlatform" />
<property name="hibernate.hbm2ddl.auto" value="validate" />
</properties>
</persistence-unit>
</persistence>

最佳答案

正如你所说,你明确地告诉 Hibernate 映射 CashFlowCategoryPKname字段到 NAME柱子;但错误实际上是关于 Hibernate 寻找连接(外键)列 category_NAMECashFlow的 table .APP.CASHFLOW 。这是因为您没有在CashFlow上指定连接列。的category字段。

根据 JPA 规范,默认连接键列名称的格式为 <ref_field_name>_<pk_column_name> (在您的情况下,这将是 category_NAME ;因此是错误消息)。我猜测 EclipseLink 执行的默认操作比规范要求的要多一些。要解决此问题,您需要在CashFlow中显式指定连接列。 :

@OneToOne
@NotNull
@JoinColumns({
@JoinColumn(name="NAME", referencedColumnName="NAME"),
@JoinColumn(name="USERNAME", referencedColumnName="USERNAME")
})
private CashFlowCategory category;

关于java - Hibernate:嵌入式 id 字段命名问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30686489/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com