-->
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.  [ 3 posts ] 
Author Message
 Post subject: how to do "on duplicated key update" in hibernate
PostPosted: Fri Apr 27, 2007 10:32 pm 
Newbie

Joined: Wed Jan 17, 2007 9:47 pm
Posts: 1
I know in sql we could use a command like
insert into ..... on duplicated key update { set x=x+y}

Does anyone knows how to do this kinda operation using hibernate?
thx


Top
 Profile  
 
 Post subject:
PostPosted: Sat Apr 28, 2007 8:13 am 
Senior
Senior

Joined: Sat Apr 21, 2007 11:01 pm
Posts: 144
Hibernate HQL is a lot more restrictive that SQL. A really good page to see all the things you can do with HQL is here: http://www.hibernate.org/hib_docs/refer ... ryhql.html
If you really want to do what you want in HQL, the only way would be to code it in Java...
So find all duplicate key records then set your values and save them back again.
Whenever I want to do anything fancy with SQL I just write a quick JDBC implimentation in my DAO layer such as:
Code:
/**
* CostYear JDBC DAO
* Contains JDBC implementations of CostYear related methods
* which can not be performed by Hibernate yet.
*
* @spring.bean
*   name = "costYearDAOJDBC"
*   autowire = "byName"
*/
public class CostYearDAOJDBC implements CostYearDAO_JDBC {
   
    private class CostYearValidVO {
        private int id = 0;
        private String name = null;
        private String valid = null;
       
        CostYearValidVO(){
        }
       
        public CostYearValidVO(
            int id,
            String name,
            String valid
        ){
            this.id = id;
            this.name = name;
            this.valid = valid;
        }

        public int getId() {
            return id;
        }

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

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getValid() {
            return valid;
        }

        public void setValid(String valid) {
            this.valid = valid;
        }
    }
   
    private class ValidForActivationRowMapper implements RowMapper  {
        public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
            CostYearValidVO costYearValidVO = new CostYearValidVO(
                rs.getInt("id"),
                rs.getString("name"),
                rs.getString("valid")
            );
            return costYearValidVO;
        }
    };
   
    /* ******************************************** *
     * JAVADOC COMMENTS IN THE INTERFACE PLEASE !!! *
     * ******************************************** */
   
    public String costYearPeriodsAreValidForActivation(int costYearId){
        String validForActivation = null;
        String sql = null;
        sql = "select\n"
            + "   CostYear.id as id,\n"
            + "   CostYear.[name] as name,\n"
            + "   case\n"
            + "       when Gaps.costYearID is not null then\n"
            + "           'form.period.costPeriod.error.gapsBetweenPeriods'\n" // There are gaps between the cost periods.
            + "       when min(CostPeriod.start_date) <> CostYear.start_date then\n"
            + "           'form.period.costPeriod.error.firstPeriodStartDate'\n" // The first cost period does not start on same day as the cost year.
            + "       when max(CostPeriod.end_date) <> CostYear.end_date then\n"
            + "           'form.period.costPeriod.error.lastPeriodEndDate'\n" // The last cost period does not end on same day as the cost year.
            + "       when DupeStartDates.costYearID is not null then\n"
            + "           'form.period.costPeriod.error.multipleStartDates'\n" // Multiple cost periods have the same start date.
            + "       when DupeEndDates.costYearID is not null then\n"
            + "           'form.period.costPeriod.error.multipleEndDates'\n" // Multiple cost periods have the same end date.
            + "       else\n"
            + "           'VALID'\n"
            + "   end as valid\n"
            + "from\n"
            + "CostYear\n"
            + "left join CostPeriod on CostPeriod.cost_year_id = CostYear.id\n"
            + "left join(\n"
            + "   select\n"
            + "       CostYear.id as costYearID\n"
            + "   from Costperiod as CostPeriodStart\n"
            + "   left join CostPeriod as CostPeriodEnd on\n"
            + "       dateAdd(ms, 3, CostPeriodStart.end_date) = CostPeriodEnd.start_date\n"
            + "       and CostPeriodStart.cost_year_id = CostPeriodEnd.cost_year_id\n"
            + "   inner join CostYear on CostYear.id = CostPeriodStart.cost_year_id\n"
            + "   where CostPeriodStart.end_date <> (\n"
            + "       select max(MaxCostPeriod.end_date)\n"
            + "       from CostPeriod as MaxCostPeriod\n"
            + "       where MaxCostPeriod.cost_year_id = CostPeriodStart.cost_year_id\n"
            + "   )\n"
            + "   and CostPeriodEnd.id is null\n"
            + "   group by CostYear.id, CostPeriodEnd.id\n"
            + ")\n"
            + "as Gaps on Gaps.costYearID = CostYear.id\n"
            + "left join(\n"
            + "   select cost_year_id as CostYearID\n"
            + "   from CostPeriod\n"
            + "   group by cost_year_id, CostPeriod.start_date\n"
            + "   having count(*) > 1\n"
            + ")\n"
            + "as DupeStartDates on DupeStartDates.costYearID = CostYear.id\n"
            + "left join(\n"
            + "   select cost_year_id as costYearID\n"
            + "   from CostPeriod\n"
            + "   group by cost_year_id, CostPeriod.end_date\n"
            + "   having count(*) > 1\n"
            + ")\n"
            + "as DupeEndDates on DupeStartDates.costYearID = CostYear.id\n"
            + "where CostYear.id = '" + costYearId + "'\n"
            + "group by\n"
            + "   CostYear.id,\n"
            + "   CostYear.[name],\n"
            + "   Gaps.costYearID,\n"
            + "   DupeStartDates.costYearID,\n"
            + "   DupeEndDates.costYearID,\n"
            + "   CostYear.start_date,\n"
            + "   CostYear.end_date\n";
        RowMapper mapper = new ValidForActivationRowMapper();
        List results = jdbcTemplate.query(sql, new RowMapperResultReader(mapper));
        if( (results != null) && (!results.isEmpty()) ){
            validForActivation = ((CostYearValidVO)(results.get(0))).getValid();
        }
        return validForActivation;
    }

    // *******************************************
    // *            SPRING  SERVICES             *
    // *******************************************
    // Services are injected automatically by Spring.
    //  ------------------------------------------------------------------------------

    private JdbcTemplate jdbcTemplate;
    /**
     * @spring.property ref = "jdbcTemplate"
     */
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
    //  ------------------------------------------------------------------------------
}

Hope that helps.

_________________
Everytime you get an answer to your question without giving credit; god kills a kitten. :(


Top
 Profile  
 
 Post subject:
PostPosted: Sat Apr 28, 2007 9:32 am 
Senior
Senior

Joined: Tue Mar 09, 2004 2:38 pm
Posts: 141
Location: Lowell, MA USA
Hi Pityme,

I think Adam's solution is way overkill for what you are asking for. There are a few ways you could achieve this. I assume that you are asking this because you are using an assigned ID generator rather than using one of the many ID generators in Hibernate?

One issue you may have with this is when using the saveOrUpdate() method. Basically, if an ID is not present, or the ID does not yet exist in the database, it will perform and insert. If the ID does exist, it will update. So using the insert into ..... on duplicated key update { set x=x+y} would cause some obvious issues with this method. Since nothing like saveOrUpdate exists in JPA, you won't have an issue.

What you could do is create your own sequence generator which could do the same thing. Another option is to use an @EntityListener and implement a @PrePersist method to perform the same logic. Either option is several times more efficient, and FAR less code than Adam's solution.

Ryan-

_________________
Ryan J. McDonough
http://damnhandy.com

Please remember to rate!


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

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.