1

I use spring and hibernate. The following situation occured and I don't know if it's really possible to implement. Will appreciate any help.

For example, there is a hibernate entity

    @Entity
public class TestEntity {
    private String field1;
    private String field2;
    private String specField;

    @Column(name = "field1")
    public String getField1() {
        return field1;
    }

    @Column(name = "field2")
    public String getField2() {
        return field2;
    }

    public String getSpecField() {
        return (field1 != null ? field1 : field2);
    }
}

And I need the value for specField to be generated by SQL query and not by java code. Something like this

    @Entity
public class TestEntity {
    private String field1;
    private String field2;
    private String specField;

    @Column(name = "field1")
    public String getField1() {
        return field1;
    }

    @Column(name = "field2")
    public String getField2() {
        return field2;
    }

    @Query(value= "COALESCE(field1, field2)")
    public String getSpecField() {
        return specField;
    }
}

I was told that there should be ability to do so. But didn't find anything that approves this.

it's not actually important what exactly query does. I need that specField will be taken by some query and not by java code. Is it possible?

Thanks for help.

UPDATE Thanks to @premkumar, for advicing to use @Formula So now I have

@Entity
public class TestEntity {
    private String field1;
    private String field2;
    private String specField;

    @Column(name = "field1")
    public String getField1() {
        return field1;
    }

    @Column(name = "field2")
    public String getField2() {
        return field2;
    }

    @Formula("COALESCE(field2, field2)")
    public String getSpecField() {
        return (field1 != null ? field1 : field2);
    }
}

But app fails to start on bean initialization with NullPointerException at org.springframework.orm.hibernate3.LocalSessionFactoryBean.newSessionFactory

I tried also the following:

  1. Put formula above "private String specField" - app started, but hibernate failed on could not find spec_field in database

  2. Put @Formula and @Transient on getter - app started, no errors, but specField is always null. It looks like hibernate totally ignored it

8
  • 1
    Why don't you use @ PrePersist or @ PreUpdate to set the value in the field for that entity? Commented Dec 8, 2015 at 18:33
  • did you mean specField should have value (field1 + ", "+ field2)? if not can you more clear Commented Dec 8, 2015 at 18:34
  • @RossiRobinsion I actually didn't know about it. I will research it now Commented Dec 8, 2015 at 18:35
  • @premkumar specField should be field1 if field2 is null or field2 if field1 is null Commented Dec 8, 2015 at 18:36
  • Those are callback methods. E.G: javabeat.net/jpa-entity-listeners-callback-methods Commented Dec 8, 2015 at 18:37

3 Answers 3

1

If you are using hibernate, try the following:

@Formula("COALESCE(field1, field2)")
public String getSpecField() {
    return specField;
}

Note:- As far as I know there is no alternative in JPA. Beware this will mixup hibernate and jpa annotations.

Sign up to request clarification or add additional context in comments.

8 Comments

Thanks! This matches perfectly my needs. But somehow adding this annotation ruins the project, and it won't start with NullPointerException at org.springframework.orm.hibernate3.LocalSessionFactoryBean.newSessionFactory. Maybe you have thoughts what this can be?
@me1111 did this work for you? if yes then when is this exception happening? what is the case when you remove the annotation? Do you still get the exception?
It's failing on bean initalization and stacktrace leads to NullPointerException in LocalSessionFactoryBean.newSessionFactory. When removed annotation, app started ok, but hibernate failed with "no spec_field column in database" when fetching. I updated my post with details
dont mixup field and getter annotations.. follow one style.. in your case keep it on getter for consistency.. remove transient annotation as hibernate will completely ignore that element... can you provide complete stack trace
seems issue related to hiberate version. stackoverflow.com/questions/3331529/… which version are you using?
|
1

Why not:

public String getSpecField() {
   return MoreObjects.firstNonNull(field1,field2);
}

4 Comments

It's important to generate specField exactly by SQL query and not by java code
Coalesce is supported by JPA 2.0 API. try select COALESCE(field1,field2) as specField, from TestEntity
Not sure if I got you right. You mean I can put it as @NativeQuery for full entity?
take a look at @SqlResultSetMapping from hibernate, it allows you to map the fields of your object to the columns retrieved by a native query
1

You can leverage the JPA Callback methods:

  1. Create a EntityListener:

    public class MyEntityListener {
    
        @PrePersist
        @PreUpdate
        public void prePersist(Object object) {
            if(object instanceOf TestEntity ) {
                object.specField  = object.field1 != null ? object.field1 : object.field2
            }
        }
    }
    
  2. Annotate your class with @EntityListener:

    @Entity
    @EntityListeners(MyEntityListener .class)
    public class TestEntity {
        private String field1;
        private String field2;
        private String specField;
    
        //default cons - getters and setters
    }
    

3 Comments

It's important to generate specField exactly by SQL query and not by java code
You need to elaborate your definition of generate by SQL Query.
I mean that hibernate should get value for specField by executing SQL

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.