tags:

views:

34

answers:

0

Hello

I'm using Hibernate with a Restrictions.in() criteria on a table with a composite id. Everything works fine when I put just one id in the query but when I put multiple id:s in the query Hibernate binds the parameters wrong.

This is the output from the jboss log:

16:48:24,882 INFO  [STDOUT] Hibernate: select this_.part_id as part1_2_0_, this_.player_id as player2_2_0_, this_.timestamp as timestamp2_0_ from user_achievements.part_player this_ where (1=1) and (this_.part_id, this_.player_id) in ((?, ?), (?, ?))
16:48:24,882 TRACE [AbstractBatcher] preparing statement
16:48:24,884 TRACE [IntegerType] binding '5' to parameter: 1
16:48:24,884 TRACE [IntegerType] binding '11' to parameter: 2
16:48:24,884 TRACE [IntegerType] binding '123' to parameter: 3
16:48:24,884 TRACE [IntegerType] binding '123' to parameter: 4

It should bind the following way:

binding '5' to parameter: 1
binding '123' to parameter: 2
binding '11' to parameter: 3
binding '123' to parameter: 4

My composite key class looks like this:

import javax.persistence.Column;
import javax.persistence.Embeddable;
import java.io.Serializable;

@Embeddable
public class PlayerPartPk implements Serializable {
    private Integer partId;
    private Integer playerId;

    @Column(name ="part_id", nullable = false)
    public Integer getPartId() {
        return partId;
    }

    public void setPartId(Integer partId) {
        this.partId = partId;
    }

    @Column(name ="player_id", nullable = false)
    public Integer getPlayerId() {
        return playerId;
    }

    public void setPlayerId(Integer playerId) {
        this.playerId = playerId;
    }

    @Override
    public boolean equals(Object other) {
        boolean result = true;

        if(!(other instanceof PlayerPartPk)) {
            return false;
        }

        Integer otherPartId = ((PlayerPartPk)other).getPartId();
        Integer otherPlayerId = ((PlayerPartPk)other).getPlayerId();

        if(this.getPartId() == null || otherPartId == null) {
            result = false;
        } else {
            result = this.getPartId().equals(otherPartId);
        }

        if(this.getPlayerId() == null || otherPlayerId == null) {
            result = false;
        } else {
            result = this.getPlayerId().equals(otherPlayerId);
        }

        return result;
    }

    @Override
    public int hashCode() {
        int code = 0;

        if(this.getPartId() != null) {
            code += this.getPartId();
        }

        if(this.getPlayerId() != null) {
            code += this.getPlayerId();
        }

        return code;
    }
}

My class looks like this:

import org.codehaus.jackson.map.annotate.JsonDeserialize;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.hibernate.annotations.Proxy;
import org.hibernate.annotations.Type;
import org.joda.time.DateTime;

import javax.persistence.*;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.io.Serializable;

@XmlRootElement
@XmlAccessorType(XmlAccessType.PROPERTY)
@Entity
@Proxy(lazy = false)
@Table(name = "part_player", schema = "user_achievements")
public class PlayerPart implements Serializable {

    private static final String PERSISTENT_DATE_TIME = "org.joda.time.contrib.hibernate.PersistentDateTime";

    private PlayerPartPk id;
    private DateTime timestamp;

    @EmbeddedId
    public PlayerPartPk getId() {
        return id;
    }

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

    @Column(name ="timestamp", nullable = true)
    @XmlJavaTypeAdapter(DateTimeXmlAdapter.class)
    @JsonSerialize(using = DateTimeJsonSerializer.class)
    @JsonDeserialize(using = DateTimeJsonDeserializer.class)
    @Type(type = PERSISTENT_DATE_TIME)
    public DateTime getTimestamp() {
        return timestamp;
    }

    public void setTimestamp(DateTime timestamp) {
        this.timestamp = timestamp;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        PlayerPart that = (PlayerPart) o;

        if (this.getId() != null ? !this.getId().equals(that.getId()) : that.getId() != null) return false;

        return true;
    }

    @Override
    public int hashCode() {
        return this.getId() != null ? this.getId().hashCode() : 0;
    }
}

and this is my hibernate criteria query:

.....

 protected final Criteria getCriteriaForSearchCriteria(final T searchCriteria) {
        Example example = Example.create(searchCriteria);
        Criteria criteria = getSession().createCriteria(persistentClass);
        criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
        return criteria.add(example);
    }


.....

public List<PlayerPart> findAllByPlayerAndPart(List<PlayerPartPk> partPks) {
        Criteria criteria = getCriteriaForSearchCriteria(new PlayerPart()).add(Restrictions.in("id", partPks));
        return criteria.list();

    }

What am I doing wrong?

Many thanks in advance.