【问题标题】:Hibernate Mapping thinking errorHibernate Mapping 思维错误
【发布时间】:2017-09-13 21:29:53
【问题描述】:

我有 2 个数据库表。首先有交易。每个交易都有一个 ID。这个 ID 也可以在我的第二张表中找到。第二张表包含费用,但我的第一张表没有关于费用的信息。现在我必须通过休眠映射获取与 1 笔交易相关的所有费用,但我不想在两个方向都有它。

贸易类:

public class Trade {
    @Id
    @Column(name = "ID")
    private Long tradeTag;

    @ElementCollection
    @CollectionTable(name = "VIE_CHARGES", joinColumns = 
    @JoinColumn(name="TRADE"))
    private List<Charge> charges;
}

收费等级:

public class Charge implements Serializable{

    private static final long serialVersionUID = 1L;
    @Id
    private String chargeType;
    @Id
    @Column(name="TRADE")
    private Long tradeTag;
}

在收费类中,我不想保留有关交易的任何信息,但在交易类中,我想保存所有交易费用的清单。我很乐意在这里得到解决方案,因为我真的不知道该怎么做。

查看收费:

create view VIE_CHARGES as 
select CHRG_TYPE AS CHARGETYPE
,TRAD_TAG AS TRADE
from TRADE_CHARGE

查看交易:

create VIEW VIE_TRADE AS 
select TRAD_TAG as ID
from TRADE 

错误是:

org.hibernate.exception.SQLGrammarException:无法提取 结果集在 org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:106) 在 org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42) 在 org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111) 在 org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:97) 在 org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:79) 在 org.hibernate.loader.Loader.getResultSet(Loader.java:2123) 在 org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1911) 在 org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1887) 在 org.hibernate.loader.Loader.doQuery(Loader.java:932) 在 org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:349) 在 org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:319) 在 org.hibernate.loader.Loader.loadCollection(Loader.java:2327) 在 org.hibernate.loader.collection.plan.LegacyBatchingCollectionInitializerBuilder$LegacyBatchingCollectionInitializer.initialize(LegacyBatchingCollectionInitializerBuilder.java:88) 在 org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:688) 在 org.hibernate.event.internal.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:75) 在 org.hibernate.internal.SessionImpl.initializeCollection(SessionImpl.java:2150) 在 org.hibernate.collection.internal.AbstractPersistentCollection$4.doWork(AbstractPersistentCollection.java:567) 在 org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:249) 在 org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:563) 在 org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:132) 在 org.hibernate.collection.internal.AbstractPersistentCollection$1.doWork(AbstractPersistentCollection.java:161) 在 org.hibernate.collection.internal.AbstractPersistentCollection$1.doWork(AbstractPersistentCollection.java:146) 在 org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:249) 在 org.hibernate.collection.internal.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:145) 在 org.hibernate.collection.internal.PersistentBag.size(PersistentBag.java:261) 在 com.mainfirst.emma.archive.trade.rims.TestDataBaseconnection.testTradeDao(TestDataBaseconnection.java:28) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(未知来源)在 java.lang.reflect.Method.invoke(未知来源)在 org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) 在 org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 在 org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) 在 org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) 在 org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75) 在 org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86) 在 org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84) 在 org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) 在 org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252) 在 org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) 在 org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) 在 org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) 在 org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) 在 org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) 在 org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) 在 org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 在 org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) 在 org.junit.runners.ParentRunner.run(ParentRunner.java:363) 在 org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) 在 org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) 在 org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) 引起:com.microsoft.sqlserver.jdbc.SQLServerException: 无效 列名称“charges_TRADE”。在 com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:216) 在 com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1515) 在 com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:404) 在 com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:350) 在 com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:5696) 在 com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:1715) 在 com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:180) 在 com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:155) 在 com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeQuery(SQLServerPreparedStatement.java:285) 在 org.apache.commons.dbcp2.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:83) 在 org.apache.commons.dbcp2.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:83) 在 org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:70) ... 50 更多

【问题讨论】:

  • 在 Trade 类中使用 @JoinColumn 参考 Charge 类中的外键列
  • @rathna 是的,但如果可能的话,我不希望收费保留任何有关交易的信息(不认为是)

标签: java hibernate hibernate-mapping


【解决方案1】:

所以在@OneToMany 的文档中有一个例子,我认为它尽可能满足我的需求。

我现在正在使用的解决方案:

public class Trade {
    @Id
    @Column(name = "ID")
    private Long tradeTag;
    @OneToMany(orphanRemoval=true)
    @JoinColumn(name="trade")
    private List<Charge> charges;
}

public class Charge implements Serializable{

    private static final long serialVersionUID = 1L;
    @Id
    private String chargeType;
    @Id
    @Column(name="TRADE")
    private Long tradeTag;
}

如果有人有更好的想法,请随时与我分享

【讨论】:

    【解决方案2】:

    如果收费对象不需要自己的生命周期(没有自己的标识符,不被多个交易引用,不应该单独存在,并且应该与它的交易一起被删除),您可以将其映射为值类型的 @ElementCollection(@ 987654322@).

    映射表和id列名可以通过@CollectionTable@JoinColumn注解来设置。它的默认值为“trade_charges”和“trade_id”。

    @OrderColumn 注释只是一点点性能提升,只有当您面临对集合进行大量更改时才需要它。它向 trade_charges 表添加了一个索引列,以识别更新/删除语句中的行。

    例如交易:

    @Entity
    public class Trade {
    
        @Id
        @Column(name = "ID")
        private Long tradeTag;
    
        @ElementCollection
        @CollectionTable(name = "charges", joinColumns = @JoinColumn(name="ID"))
        @OrderColumn
        private List<Charge> charges;
    
    }
    

    还有收费:

    @Embeddable
    public class Charge {
    
        private String chargeType;
    
    }
    

    【讨论】:

    • 使用您的解决方案,我在charges_Trade 上收到无效的列名错误。知道如何删除名称中的charges_ 吗?
    • 嗯。不应该有这样的列。收费表应包含以charge...开头的两列,即charge_type 和charges_order。正在使用哪个数据库?
    • 它是一个 ms sql 服务器。我使用视图,因为不应以任何方式更改任何数据。因此我创建了一些视图来将类映射到。如果我将列表名称更改为任何内容,则错误中的列名称将更改为相同的值
    • 那么有一个给定的数据库结构(包含数据),你不能改变它?然后您必须根据现有列调整映射中的名称并删除@OrderColumn,因为这会添加另一列。
    • 是的,我无法改变它。但我似乎无法正确更改名称。总是得到无效的列名错误。列名总是列表名_charge id
    【解决方案3】:

    在休眠中,最好的方法是使用双向@OneToMany 并保持关系的双方同步。像这样的:

    @Entity(name = "Person")
    public class Person {
    
        @Id
        @GeneratedValue
        private Long id;
        private String name;
        @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "person")
        private Set<Phone> phones=new HashSet<Phone>();
    //getters and setters
    public void addPhone(Phone phone) {
            phone.setPerson(this);
            phones.add(phone);
        }
    
        public void removePhone(Phone phone) {
            phone.setPerson(null);
            phones.remove(phone);
        }
    }
    

    和电话实体:

    @Entity(name = "Phone")
    public class Phone {
    
        @Id
        @GeneratedValue
        private Long id;
    
        @Column(name = "`number`")
        private String number;
    
        @ManyToOne(fetch = FetchType.LAZY)
        @JoinColumn(name = "person_id", nullable = false)
        private Person person;
    

    阅读文档https://docs.jboss.org/hibernate/orm/current/userguide/html_single/Hibernate_User_Guide.html#associations-one-to-many

    【讨论】:

    • 这正是我不想做的事情
    猜你喜欢
    • 2013-09-24
    • 1970-01-01
    • 2016-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多