1

I got next exception:

Caused by: com.impetus.kundera.KunderaException: com.datastax.driver.core.exceptions.InvalidQueryException: Invalid INTEGER constant (1) for promo_code_id of type ascii
    at com.impetus.kundera.client.cassandra.dsdriver.DSClient.execute(DSClient.java:510) [kundera-cassandra-ds-driver.jar:]
    at com.impetus.kundera.client.cassandra.dsdriver.DSClient.executeQuery(DSClient.java:415) [kundera-cassandra-ds-driver.jar:]
    at com.impetus.client.cassandra.query.CassQuery.recursivelyPopulateEntities(CassQuery.java:245) [kundera-cassandra.jar:]
    at com.impetus.kundera.query.QueryImpl.fetch(QueryImpl.java:1266) [kundera-core.jar:]
    at com.impetus.kundera.query.QueryImpl.getResultList(QueryImpl.java:187) [kundera-core.jar:]
    at com.impetus.kundera.query.KunderaTypedQuery.getResultList(KunderaTypedQuery.java:250) [kundera-core.jar:]

during executing the next block of code:

public List<ActivatedPromoCode> findRegistrationPromoBetween(List<String> promoCodeIds, Date startDate, Date endDate)
            throws DAOException {
        try {
            if (promoCodeIds == null ) return null;

            TypedQuery<ActivatedPromoCode> query = getEM().createQuery(
                    "select apc from ActivatedPromoCode apc where apc.promoCodeId in ?1 " +
                            "and apc.isRegistrationPromo = true " +
                            "and apc.activationTimestamp > ?2 and apc.activationTimestamp < ?3",
                    ActivatedPromoCode.class);
            query.setParameter(1, promoCodeIds);
            query.setParameter(2, startDate);
            query.setParameter(3, endDate);

            try {
                return query.getResultList();
            } catch (NoResultException e) {
                return null;
            }
        } catch (Exception e) {
            throw new DAOException("Search activated promo codes activated during registration", e);
        }

In logs I see the next record that shows which query Kundera sends to Cassandra:

09:35:22,963 ERROR [com.impetus.kundera.client.cassandra.dsdriver.DSClient] (Thread-0 (HornetQ-client-global-threads-1819772796)) Error while executing query SELECT * FROM "activated_promo_code" WHERE "promo_code_id" IN (1) AND "is_registration_promo" = true AND "activation_timestamp" > '1427857200000' AND "activation_timestamp" < '1428116400000' LIMIT 100  ALLOW FILTERING.

Definition of structure in database:

 describe table activated_promo_code;

CREATE TABLE ustaxi.activated_promo_code (
    id ascii,
    promo_code_id ascii,
    activation_timestamp timestamp,
    code ascii,
    current_target_bonus int,
    is_active boolean,
    is_registration_promo boolean,
    target_id ascii,
    used_counts int,
    PRIMARY KEY (id, promo_code_id)
) WITH CLUSTERING ORDER BY (promo_code_id ASC)
    AND bloom_filter_fp_chance = 0.01
    AND caching = '{"keys":"ALL", "rows_per_partition":"NONE"}'
    AND comment = ''
    AND compaction = {'min_threshold': '4', 'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy', 'max_threshold': '32'}
    AND compression = {'sstable_compression': 'org.apache.cassandra.io.compress.LZ4Compressor'}
    AND dclocal_read_repair_chance = 0.1
    AND default_time_to_live = 0
    AND gc_grace_seconds = 864000
    AND max_index_interval = 2048
    AND memtable_flush_period_in_ms = 0
    AND min_index_interval = 128
    AND read_repair_chance = 0.0
    AND speculative_retry = '99.0PERCENTILE';
CREATE INDEX activatedpromocodebypromocodeid ON ustaxi.activated_promo_code (promo_code_id);
CREATE INDEX activatedpromocodebyactivationts ON ustaxi.activated_promo_code (activation_timestamp);
CREATE INDEX activatedpromocodebycode ON ustaxi.activated_promo_code (code);
CREATE INDEX activatedpromocodebyregistrationflag ON ustaxi.activated_promo_code (is_registration_promo);
CREATE INDEX activatedpromocodebytargetid ON ustaxi.activated_promo_code (target_id);

Class declaration:

@Entity
@Table(name = "activated_promo_code")
public class ActivatedPromoCode {

    @Id
    @GeneratedValue
    @Column(name = "id", nullable = false, unique = true)
    private String id;

    @Column(name = "promo_code_id")
    private String promoCodeId;

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

    @Column(name = "target_id")
    private String targetId;

    @Column(name = "activation_timestamp")
    private Date activationTimestamp;

    @Column(name = "current_target_bonus")
    private Integer currentTargetBonus;

    @Column(name = "is_active")
    private Boolean isActive;

    @Column(name = "used_counts")
    private Integer usedCounts;

    @Column(name = "is_registration_promo")
    private Boolean isRegistrationPromo;

    // Getters and setters
}

Can anybody explain me why Kundera transforms String "1" to Integer 1? And how can I avoid that?

Thanks

Dolzhenok
  • 78
  • 6

2 Answers2

2

Kundera does not transform String to Integer. Mapping of your table - entity is not correct (you have composite key in table, but it is not defined in entity).

In order to use composite key in Cassandra using Kundera you need to define it as an embeddedId.

Embeddable class:-

@Embeddable
public class Myid
{
    @Column(name = "id", nullable = false, unique = true)
    private String id;

    @Column(name = "promo_code_id")
    private String promoCodeId;

    //setters and getters
}

Entity class:-

@Entity
@Table(name = "activated_promo_code")
public class ActivatedPromoCode {

@EmbeddedId
private Myid myid;           //EmbeddedId

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

@Column(name = "target_id")
private String targetId;

@Column(name = "activation_timestamp")
private Date activationTimestamp;

@Column(name = "current_target_bonus")
private Integer currentTargetBonus;

@Column(name = "is_active")
private Boolean isActive;

@Column(name = "used_counts")
private Integer usedCounts;

@Column(name = "is_registration_promo")
private Boolean isRegistrationPromo;

// Getters and setters
}

And replace your where apc.promoCodeId in TypedQuery to where apc.myid.promoCodeId.

You can refer this for more info on composite keys.

karthik manchala
  • 13,492
  • 1
  • 31
  • 55
  • There is no deal in composite key, problem is present when I use composit key which consist of 2 fields and when I use simple one field key. If you tell that Kundera doesn't transform types why the query looks like `SELECT * FROM "activated_promo_code" WHERE "promo_code_id" IN (1) AND "is_registration_promo" = true AND "activation_timestamp" > '1427857200000' AND "activation_timestamp" < '1428116400000' LIMIT 100 ALLOW FILTERING` after inserting String values into IN operator? – Dolzhenok Apr 06 '15 at 14:03
  • Yes you are right, it should not happen. I tried the same with your entity and it is working fine. Which version of Kundera are you using? – karthik manchala Apr 06 '15 at 14:28
  • The latest one 2.16 And you got a string value '1' in IN operator like `IN ('1')` in your query to Cassandra? – Dolzhenok Apr 06 '15 at 14:34
  • Does your entities contain any relations? – karthik manchala Apr 07 '15 at 06:59
  • Yes. Current class has `@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER) @JoinColumn(name = "promo_code_id", referencedColumnName = "id") private PromoCode promoCode;` – Dolzhenok Apr 07 '15 at 07:21
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/74612/discussion-between-karthik-manchala-and-dolzhenok). – karthik manchala Apr 07 '15 at 07:29
0

So, the problem was not in Kundera but in model class definition. Class contained 2 fields that mapped to one database field. Sometimes field promo_code_id casts to String and we got correct work and sometimes it casts to PromoCode and we got incorrect work. So, the solution is to use more appropriate schema definition.

Chat with discussions: https://chat.stackoverflow.com/rooms/74612/discussion-between-karthik-manchala-and-dolzhenok

Community
  • 1
  • 1
Dolzhenok
  • 78
  • 6