-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 
Author Message
 Post subject: Set of UserTypes: delete with bad param count to nullSafeSet
PostPosted: Fri Feb 22, 2008 11:01 am 
Newbie

Joined: Tue Aug 28, 2007 12:54 pm
Posts: 16
Location: Munich, Germany
Hi all,

I have a Set of (Composite)UserTypes that work well for reading and writing (insert),
calling nullSafeSet with an insert containing three parameter placeholders for my
three columns.

However, when I update the set, the statement passed to nullSafeSet is a delete
statement with only one parameter placeholder. Obviously, setting three columns
here is not supported.

Am I supposed to map the User type in another way ? (composite-element maybe!?)

Hibernate version: 3.2.5

Mapping documents:

Code:
PriceData.hbm.xml:
<hibernate-mapping>
    <class name="myapp.business.component.supplymasterdata.emea.types.entitytypes.PriceData"
        table="im_se_price_data" lazy="true">
        <id name="id">
...
        <set name="pricesSet" cascade="all" table="im_se_price_data_to_money" outer-join="true" lazy="false">
            <key foreign-key="money_id"/>
            <element type="myapp.common.foundation.basetypes.MoneyWithExchangeRateUserType">
                <column name="currency" length="3"/>
                <column name="amount" />
                <column name="rate"   not-null="true"/>
            </element>
        </set>
       
    </class>
</hibernate-mapping>

PriceData.java:
...
    private Set<MoneyWithExchangeRate> pricesSet = new HashSet<MoneyWithExchangeRate>();
    protected Set<MoneyWithExchangeRate> getPricesSet() {
        return pricesSet;
    }

    protected void setPricesSet(Set<MoneyWithExchangeRate> prices) {
        this.pricesSet = prices;
    }
...

MoneyWithExchangeRate.java:
...
    public double getExchangeRate() {
        return exchangeRate;
    }
    protected void setExchangeRate(double exchangeRate) {
        this.exchangeRate = exchangeRate;
    }
    public Currency getCurrency() {
        return currency;
    }
    protected long getAmount() {
        return amount;
    }
    protected void setAmount(long amount) {
        this.amount = amount;
    }
    protected void setCurrency(Currency currency) {
        this.currency = currency;
    }
...

MoneyWithExchangeRateUserType.java:
...
public class MoneyWithExchangeRateUserType implements CompositeUserType, Serializable {

    public MoneyWithExchangeRateUserType() {
        super();
    }
    public String[] getPropertyNames() {
        return new String[] { "currency", "amount", "rate" };
    }
    public Type[] getPropertyTypes() {
        return new Type[] { Hibernate.STRING, Hibernate.LONG, Hibernate.DOUBLE };
    }
    public Object getPropertyValue(Object component, int property) throws HibernateException {
        MoneyWithExchangeRate money = (MoneyWithExchangeRate) component;
        switch (property) {
        case 0:
            return money.getCurrency();
        case 1:
            return new Long(money.amount);// yes really access the attribute here directly
        case 2:
            return new Double(money.getExchangeRate());// yes really access the attribute here directly
        default:
            throw new ApplicationRuntimeException("That should really never happen: we got a request for property: " + property);
        }
    }
    public void setPropertyValue(Object component, int property, Object value) throws HibernateException {
        // intended to be empty
    }
    public Class returnedClass() {
        return MoneyWithExchangeRate.class;
    }
    public boolean equals(Object money1, Object money2) throws HibernateException {
        if (money1 == money2) return true;
        if (money1 == null || money2 == null) return false;
        return money1.equals(money2);
    }
    public int hashCode(Object arg0) throws HibernateException {
        return arg0.hashCode();
    }
    public Object nullSafeGet(ResultSet resultSet, String[] names, SessionImplementor session, Object owner) throws HibernateException,
            SQLException {
        CurrencyService currencyService = (CurrencyService) ServiceRegistry.lookup(CurrencyService.class);
        Currency currency = null;
        if (resultSet == null) return null;
        String currencyAbbreviation = resultSet.getString(names[0]);
        // If currency id retrieved ahs a value of 0 or is null then the default
        // currency is retrieved. This
        // has been done so that there is a compatibility with M1 code
        if (currencyAbbreviation == null) {
            currency = currencyService.defaultCurrency();
        } else {
            currency = currencyService.getCurrency(currencyAbbreviation);
        }
        long value = resultSet.getLong(names[1]);
        double rate = resultSet.getDouble(names[2]);
        // We have to use the setter here,
        // as the corresponding constructor
        // will convert the input to the internal representation
        MoneyWithExchangeRate m = new MoneyWithExchangeRate();
        m.setAmount(value);
        m.setCurrency(currency);
        m.setExchangeRate(rate);
        return m;

    }
    public void nullSafeSet(PreparedStatement statement, Object value, int index, SessionImplementor session) throws HibernateException,
            SQLException {
        if (value == null) {
            statement.setNull(index, Types.VARCHAR);
            statement.setNull(index + 1, Types.INTEGER);
            statement.setNull(index + 2, Types.DOUBLE);
        } else {
            MoneyWithExchangeRate amount = (MoneyWithExchangeRate) value;
            String currencyAbbreviation = amount.getCurrency().getAbbreviation();
            statement.setString(index, currencyAbbreviation);
            statement.setLong(index + 1, amount.amount); // yes, intended to access the attribute directly
            statement.setDouble(index + 2, amount.getExchangeRate());
        }
    }
    public Object deepCopy(Object value) throws HibernateException {
        return value;
    }
    public boolean isMutable() {
        return false;
    }
    public Serializable disassemble(Object value, SessionImplementor session) throws HibernateException {

        return (Serializable) value;
    }
    public Object assemble(Serializable cached, SessionImplementor session, Object owner) throws HibernateException {

        return cached;
    }
    public Object replace(Object value, Object arg1, SessionImplementor session, Object arg3) throws HibernateException {

        return null;
    }
}


Now, putting a breakpoint at the beginning of the nullSafeSet, I see that upon the
successful insert, I get a statement
Code:
insert into im_se_price_data_to_money (id, currency, amount, rate) values (668, ?, ?, ?)


But updating the set gives me a
Code:
delete from im_se_price_data_to_money where id=815 and rate=?

and now the nullSafeSet fails, obviously, with
Code:
2008-02-22 13:05:13,557 DEBUG http-8080-Processor23 org.hibernate.SQL - delete from im_se_price_data_to_money where id=? and rate=?
2008-02-22 13:05:13,566 WARN  http-8080-Processor23 org.hibernate.util.JDBCExceptionReporter - SQL Error: 0, SQLState: 22023
2008-02-22 13:05:13,566 ERROR http-8080-Processor23 org.hibernate.util.JDBCExceptionReporter - Der Spaltenindex 3 ist ausserhalb des gültigen Bereichs. Anzahl Spalten: 2.
2008-02-22 13:05:13,567 ERROR http-8080-Processor23 org.hibernate.event.def.AbstractFlushingEventListener - Could not synchronize database state with session
org.hibernate.exception.DataException: could not delete collection rows: [myapp.business.component.supplymasterdata.emea.types.entitytypes.PriceData.pricesSet#815]
   at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:77)
   at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
   at org.hibernate.persister.collection.AbstractCollectionPersister.deleteRows(AbstractCollectionPersister.java:1292)
   at org.hibernate.action.CollectionUpdateAction.execute(CollectionUpdateAction.java:54)
   at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:250)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:234)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:144)
   at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
   at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
   at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
   at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
   at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
   at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:558)
   at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:662)
   at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:632)
   at myapp.webapp.support.filter.transaction.TransactionSetupFilter.doFilter(TransactionSetupFilter.java:108)
   at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
   at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
   at myapp.webapp.support.filter.responseheader.ResponseHeaderFilter.doFilter(ResponseHeaderFilter.java:43)
   at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
   at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
   at myapp.webapp.support.filter.logging.ClickPathRecordingFilter.doFilter(ClickPathRecordingFilter.java:61)
   at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
   at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
   at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:210)
   at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:174)
   at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
   at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
   at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
   at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:151)
   at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:870)
   at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:665)
   at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:528)
   at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:81)
   at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:685)
   at java.lang.Thread.run(Thread.java:637)
Caused by: org.postgresql.util.PSQLException: Der Spaltenindex 3 ist ausserhalb des gültigen Bereichs. Anzahl Spalten: 2.
   at org.postgresql.core.v3.SimpleParameterList.bind(SimpleParameterList.java:52)
   at org.postgresql.core.v3.SimpleParameterList.setLiteralParameter(SimpleParameterList.java:113)
   at org.postgresql.jdbc2.AbstractJdbc2Statement.bindLiteral(AbstractJdbc2Statement.java:2106)
   at org.postgresql.jdbc2.AbstractJdbc2Statement.setLong(AbstractJdbc2Statement.java:1165)
   at org.apache.commons.dbcp.DelegatingPreparedStatement.setLong(DelegatingPreparedStatement.java:239)
   at myapp.common.foundation.basetypes.MoneyWithExchangeRateUserType.nullSafeSet(MoneyWithExchangeRateUserType.java:112)
   at org.hibernate.type.CompositeCustomType.nullSafeSet(CompositeCustomType.java:219)
   at org.hibernate.persister.collection.AbstractCollectionPersister.writeElementToWhere(AbstractCollectionPersister.java:784)
   at org.hibernate.persister.collection.AbstractCollectionPersister.deleteRows(AbstractCollectionPersister.java:1256)
   ... 33 more
2008-02-22 13:05:13,707 ERROR http-8080-Processor23 myapp.webapp.support.filter.transaction.TransactionSetupFilter - doFilter() - internal error while closing down exception: org.springframework.dao.InvalidDataAccessResourceUsageException: could not delete collection rows: [myapp.business.component.supplymasterdata.emea.types.entitytypes.PriceData.pricesSet#815]; nested exception is org.hibernate.exception.DataException: could not delete collection rows: [myapp.business.component.supplymasterdata.emea.types.entitytypes.PriceData.pricesSet#815]
org.springframework.dao.InvalidDataAccessResourceUsageException: could not delete collection rows: [myapp.business.component.supplymasterdata.emea.types.entitytypes.PriceData.pricesSet#815]; nested exception is org.hibernate.exception.DataException: could not delete collection rows: [myapp.business.component.supplymasterdata.emea.types.entitytypes.PriceData.pricesSet#815]
   at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:616)
   at org.springframework.orm.hibernate3.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:690)
   at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:566)
   at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:662)
   at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:632)
   at myapp.webapp.support.filter.transaction.TransactionSetupFilter.doFilter(TransactionSetupFilter.java:108)
   at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
   at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
   at myapp.webapp.support.filter.responseheader.ResponseHeaderFilter.doFilter(ResponseHeaderFilter.java:43)
   at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
   at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
   at myapp.webapp.support.filter.logging.ClickPathRecordingFilter.doFilter(ClickPathRecordingFilter.java:61)
   at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
   at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
   at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:210)
   at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:174)
   at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
   at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
   at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
   at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:151)
   at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:870)
   at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:665)
   at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:528)
   at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:81)
   at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:685)
   at java.lang.Thread.run(Thread.java:637)
Caused by: org.hibernate.exception.DataException: could not delete collection rows: [myapp.business.component.supplymasterdata.emea.types.entitytypes.PriceData.pricesSet#815]
   at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:77)
   at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
   at org.hibernate.persister.collection.AbstractCollectionPersister.deleteRows(AbstractCollectionPersister.java:1292)
   at org.hibernate.action.CollectionUpdateAction.execute(CollectionUpdateAction.java:54)
   at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:250)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:234)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:144)
   at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
   at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
   at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
   at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
   at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
   at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:558)
   ... 23 more
Caused by: org.postgresql.util.PSQLException: Der Spaltenindex 3 ist ausserhalb des gültigen Bereichs. Anzahl Spalten: 2.
   at org.postgresql.core.v3.SimpleParameterList.bind(SimpleParameterList.java:52)
   at org.postgresql.core.v3.SimpleParameterList.setLiteralParameter(SimpleParameterList.java:113)
   at org.postgresql.jdbc2.AbstractJdbc2Statement.bindLiteral(AbstractJdbc2Statement.java:2106)
   at org.postgresql.jdbc2.AbstractJdbc2Statement.setLong(AbstractJdbc2Statement.java:1165)
   at org.apache.commons.dbcp.DelegatingPreparedStatement.setLong(DelegatingPreparedStatement.java:239)
   at myapp.common.foundation.basetypes.MoneyWithExchangeRateUserType.nullSafeSet(MoneyWithExchangeRateUserType.java:112)
   at org.hibernate.type.CompositeCustomType.nullSafeSet(CompositeCustomType.java:219)
   at org.hibernate.persister.collection.AbstractCollectionPersister.writeElementToWhere(AbstractCollectionPersister.java:784)
   at org.hibernate.persister.collection.AbstractCollectionPersister.deleteRows(AbstractCollectionPersister.java:1256)
   ... 33 more


Note: "Der Spaltenindex 3 ist ausserhalb des gültigen Bereichs. Anzahl Spalten: 2." means
"The column index 3 is outside the allowed range. columns: 2"

Name and version of the database you are using: PostgreSQL 8

Any idea appreciated :-)

Cheers, Tom.

_________________
www.tomeicher.de


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.