0
votes

I have a 2 database tables. First has trades in it. Each Trade has an ID. This ID is also found in my 2nd table. the 2nd table contains charges, but my first table has no information about the charges. now i have to get all charges which are connected to 1 trade by hibernate mapping, but i don't want to have it in both directions.

Trade Class:

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

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

Charge class:

public class Charge implements Serializable{

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

In charge class, i don't want to hold any information about the trade, but in trade class a list of all charges for the trade. I would be very happy to get a solution here, as i have really no idea how to do it.

view for charge:

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

view for trade:

create VIEW VIE_TRADE AS 
select TRAD_TAG as ID
from TRADE 

error is:

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

3
Use @JoinColumn in Trade class with reference to foreign key column in Charge classrathna
@rathna yeah, but i dont want the charge to hold any information about the trade if possible (don't think it is)XtremeBaumer

3 Answers

1
votes

If the charge objects do not need an own lifecycle (no own identifier, not referenced by multiple trades, should not exist alone and should be and deleted with it's trade) you could map it as @ElementCollection of value types (@Embeddable).

The mapped table and id column name could be set by @CollectionTable and @JoinColumn annotations. It's defaults are "trade_charges" and "trade_id".

The @OrderColumn annotation is just a little performance boost, you only need it when you face a lot of changes to the collection. It adds an index column to the trade_charges table to identify rows on update / delete statements.

For example the Trade:

@Entity
public class Trade {

    @Id
    @Column(name = "ID")
    private Long tradeTag;

    @ElementCollection
    @CollectionTable(name = "charges", joinColumns = @JoinColumn(name="ID"))
    @OrderColumn
    private List<Charge> charges;

}

And the Charge:

@Embeddable
public class Charge {

    private String chargeType;

}
1
votes

In hibernate it is the best approach to use bidirectional @OneToMany and keep both sides of relation in sync. Smth like this:

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

And phone entity:

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

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

0
votes

So in the docs to @OneToMany there was an example of which i think it fits my needs as much as possible.

Solution i am working with now:

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

if someone has any better idea feel free to share with me