Hibernate Grouping query - 나중에 코드 수정해서 공개…

2 minute read

CreateQuery와 도메인

-- Table: topic_trend

– DROP TABLE topic_trend;

CREATE TABLE topic_trend ( topic_trend_id bigint NOT NULL, analysis_date timestamp without time zone, analysis_period timestamp without time zone, rising double precision, steady double precision, term character varying(255), type_contents character varying(200) NOT NULL, type_period character varying(20), CONSTRAINT topic_trend_pkey PRIMARY KEY (topic_trend_id) ) WITH ( OIDS=FALSE ); ALTER TABLE topic_trend OWNER TO vital;

– Index: ix_topic_trend

– DROP INDEX ix_topic_trend;

CREATE INDEX ix_topic_trend ON topic_trend USING btree (type_contents COLLATE pg_catalog.”default”, analysis_date);

Hibernate Domani

package com.kt.vital.domain.model.statistics;

import com.google.common.base.Objects; import kr.debop4j.data.model.AnnotatedEntityBase; import lombok.Getter; import lombok.Setter; import org.hibernate.annotations.DynamicInsert; import org.hibernate.annotations.DynamicUpdate; import org.hibernate.annotations.Index; import org.hibernate.annotations.Type; import org.hibernate.validator.constraints.NotEmpty; import org.joda.time.DateTime;

import javax.persistence.*;

/** * 토픽 추세 정보 * 토픽 분석 * * @author archmagece@gmail.com * @since 2013.05.13 * */ @Entity @Table(name = “TopicTrend”) //@Table(name = “TopicTrend”, uniqueConstraints = {@UniqueConstraint(name=”topic_trend_unique”, columnNames = {“typeContents”, “analysisDate”})}) @org.hibernate.annotations.Table(appliesTo = “TOPIC_TREND”, indexes = { @Index(name = “ix_topic_trend”, columnNames = { “typeContents”, “analysisDate” }) }) //@Table(name=”TopicTrend”) @DynamicInsert @DynamicUpdate @Getter @Setter public class TopicTrend extends AnnotatedEntityBase {

private static final long serialVersionUID = -4845644155814369186L;

//protected TopicTrend() {}

//public TopicTrend(String typePeriod, String typeContents, DateTime analysisPeriod, DateTime analysisDate, String term, double steady, double rising) {}
public TopicTrend() {}

/\*\*
 \* TopicTrend Id
 \*/
@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = "topic\_trend\_id\_seq")
@SequenceGenerator(name="topic\_trend\_id\_seq", sequenceName = "topic\_trend\_id\_seq")
@Column(name = "TopicTrendId")
private Long id;

/\*\*
 \* 분석주기
 \*/ //    @NotEmpty
@Column(name = "TypePeriod", nullable = true, length = 20)
private String typePeriod;

/\*\*
 \* 컨텐츠(컬렉션)
 \*/
@NotEmpty
@Column(name = "TypeContents", nullable = true, length = 200)
private String typeContents;

/\*\*
 \* 분석 시작일
 \*/ //    @NotEmpty
@Type(type = "kr.debop4j.data.hibernate.usertype.JodaDateTimeUserType")
@Column(name = "AnalysisPeriod", nullable = true)
private DateTime analysisPeriod;

/\*\*
 \* 분석일
 \*/ //    @NotEmpty
@Type(type = "kr.debop4j.data.hibernate.usertype.JodaDateTimeUserType")
@Column(name = "AnalysisDate", nullable = true)
private DateTime analysisDate;

/\*\*
 \* 용어
 \*/ //    @NotEmpty
@Column(name = "Term", nullable = true)
private String term;

/\*\*
 \* 종합
 \*/
@Column(nullable = true)
private double steady;

/\*\*
 \* 급상승
 \*/
@Column(nullable = true)
private double rising;

@Override
protected Objects.ToStringHelper buildStringHelper() {
    return super.buildStringHelper()
            .add("id", id)
            .add("typePeriod", typePeriod)
            .add("typeContents", typeContents)
            .add("analysisPeriod", analysisPeriod)
            .add("analysisDate", analysisDate)
            .add("term", term)
            .add("steady", steady)
            .add("rising", rising);
} }

원하는 SelectQuery

select date_part(‘day’, this_.analysis_date) as time_group, sum(this_.RISING) as y1_, this_.TERM as y2_ from TOPIC_TREND this_ group by time_group, this_.TERM order by time_group asc, y1_ desc limit ?

요 쿼리를 만드는 방법…

projectionList.add(Projections.alias(Projections.sqlGroupProjection( “date_part(‘day’,{alias}.analysis_date) as time_group, term”, “time_group, term”, new String[]{“time_group, term”}, new Type[] {DoubleType.INSTANCE, StringType.INSTANCE} ),”time_group”));

에러메세지 org.hibernate.QueryException: not a single-length projection: time_group 그룹을 두개씩 써놓으면 안된다는 메세지….처리해준다.

private int pageSize=10; public List dataByTimeSection(TIME_SECTION timeSection, int page) { // int wordPerPage = 10; // int endWord = wordPerPage*page; // int startWord = endWord - 9;

    session = UnitOfWorks.getCurrentSession();

    DetachedCriteria dc = DetachedCriteria.forClass(TopicTrend.class);
    criteria = session.createCriteria(TopicTrend.class);
    ProjectionList projectionList = Projections.projectionList();

    switch (timeSection){
        case HOUR:
            projectionList.add(Projections.sqlGroupProjection(
                    "date\_part('hour',{alias}.analysis\_date) as time\_group",
                    "time\_group",
                    new String\[\]{"time\_group"},
                    new Type\[\] {DoubleType.INSTANCE}
            ), "time\_group");
            break;
        case DAY:
            projectionList.add(Projections.alias(Projections.sqlGroupProjection(
                    "date\_part('day',{alias}.analysis\_date) as time\_group",
                    "time\_group",
                    new String\[\]{"time\_group, term"},
                    new Type\[\] {DoubleType.INSTANCE, StringType.INSTANCE}
            ),"time\_group"));
            break;
        case WEEK:
            projectionList.add(Projections.sqlGroupProjection(
                    "date\_part('week',{alias}.analysis\_date) as time\_group",
                    "time\_group",
                    new String\[\]{"time\_group"},
                    new Type\[\] {DoubleType.INSTANCE}
            ),"time\_group"));
            break;
        case MONTH:
            projectionList.add(Projections.sqlGroupProjection(
                    "date\_part('month',{alias}.analysis\_date) as time\_group",
                    "time\_group",
                    new String\[\]{"time\_group"},
                    new Type\[\] {DoubleType.INSTANCE}
            ),"time\_group"));
            break;
        default:
            //freak //                projectionList.add(Projections.sqlGroupProjection( //                        "sum(rising) as cnt, date\_part('month', {alias}.analysis\_date) as time\_group, term", //                        "date\_part('month', {alias}.analysis\_date), term", //                        new String\[\]{"cnt", "time\_group", "term"}, //                        new Type\[\] {DoubleType.INSTANCE, DoubleType.INSTANCE, StringType.INSTANCE} //                ));
            break;
    }

    criteria.setProjection(
            projectionList
                    .add(Projections.alias(
                            Projections.sum("rising"),"cnt")
                    )
                    .add(Projections.groupProperty("term")
                    )
    )
    .addOrder(Order.asc("time\_group"))
    .addOrder(Order.desc("cnt"));

    criteria.setFirstResult((page-1)\*pageSize);
    criteria.setMaxResults(page \* pageSize);

    return criteria.list();

}

public void testDataByTimeSectionUsingDay() throws Exception { List<Object[]> list = keywordRankingService.dataByTimeSection(KeywordRankingService.TIME_SECTION.DAY, 1); for( Object[] objects : list){ System.out.println(objects); for(Object obj : objects){ // System.out.println(obj instanceof Double); // System.out.println(obj instanceof String); System.out.print(obj); } } System.out.println(list); }