65

We have some Hibernate getter methods annotated with both @Column and @Basic.

We get an exception if we don't have the corresponding setter. Why is this?

In our case we are deriving the value returned from the getter (to get stored in the DB) and the setter has no functional purpose. So we just have an empty method to get around the error condition..

Marcus Leon
  • 55,199
  • 118
  • 297
  • 429
  • Just autogenerate model objects. Eclipse, Dali and/or Hibernatetools can do this in a few clicks. No need to spend hours on writing getters/setters nor worrying about its correctness and presence. – BalusC Apr 20 '10 at 17:42

5 Answers5

85

As others have mentioned, if you annotate a property getter method, then Hibernate uses the setter when reading values from the database. Basically, Hibernate assumes that anything that it is writing to the database will eventually need to be read from the database. This implies that if you annotate a getter, then it needs to call a setter when reading the object from the database.

You can make the setter private (Hibernate will use reflection to access the setter). This is great way to preserve the contract of your class while still using Hibernate for relational mapping.

If the field is derived from other properties in the class, then why are you storing it in the database? You can use the @Transient annotation to mark the field that it shouldn't be stored in the database. You can even use the @Formula annotation to have Hibernate derive the field for you (it does this by using the formula in the query it sends to the database).

Jim Hurne
  • 7,187
  • 4
  • 44
  • 44
12

You should annotate your classes with the @Entity(access = AccessType.FIELD) and annotate your attributes. This should solve your problem. The setter is the best way to support refactoring. And what's the problem with having the little setter there.

naXa stands with Ukraine
  • 35,493
  • 19
  • 190
  • 259
khmarbaise
  • 92,914
  • 28
  • 189
  • 235
  • 5
    Just put the annotations to the attributes instead of the getter then it should work as well (Read the annotation doc about Access Type). – khmarbaise Apr 20 '10 at 16:22
  • No problem with having the setter per se.. it's just extra code.. we are only using Hibernate to write to the db, never to read.. – Marcus Leon Apr 20 '10 at 17:19
  • 2
    Bear in mind that changing the access type from property to field can have side effect. Hibernate will no longer use the getters and setters, but will access the fields directly via reflection, meaning if you have any special logic in your getters and setters, it will no longer be called. – Jherico Apr 20 '10 at 18:19
  • 3
    I feel like they should never even have special logic implemented ;) – chzbrgla Feb 22 '12 at 15:52
  • 1
    it shows me an error . it look like @Entity don't have any parameter name access. – Saif Nov 15 '14 at 07:37
  • 4
    @Saif In this post not javax.persistence.Entity was mentioned, but org.hibernate.annotations.Entity. But after 4.1 version of Hibernate it's deprecated, so you could us @javax.persistence.Access(javax.persistence.AccessType.FIELD) – AlexB Apr 21 '17 at 08:16
10

Set access="field" if you do not want to use setters:

<class name="com.demo.hibernate.Country" table="country">
  <id name="countryId" column="id" type="int">
    <generator class="increment" />
  </id>
  <property name="name" column="name" access="field" type="string" />
  <property name="countryCode" column="country_code" access="field" type="string" />
</class>
Michael
  • 8,362
  • 6
  • 61
  • 88
vsingh
  • 6,365
  • 3
  • 53
  • 57
1

Hibernate uses set method to initialize the entity which you're reading from your DB.

Maybe, if you make access modifiers of entity fields default or protected or public then Hibernate will initialize fields directly without using setter (I read something about it but I'm not sure that it works). But using setter is much more preferred way.

Roman
  • 64,384
  • 92
  • 238
  • 332
-1

If you don't use setters and use private attributes, Hibernate would have to retrieve Fields by reflection and do field.setAccessible(true). I don't think Hibernate does that.

I don't really know if we can tell to Hibernate to do that, but as far as i remember, default config is using setters... Put a log/sysout on a set and you'll see that it uses the setter.

Sebastien Lorber
  • 89,644
  • 67
  • 288
  • 419
  • 2
    -1 because if the field or property is private, Hibernate does exactly that (use field.setAccessible(true)). – Jim Hurne Apr 20 '10 at 17:29
  • Actually i'm pretty sure that while using JPA / entity beans with all private attributes, hibernate (3.4 i think) was using the setter... But perhaps if there is no setter it does that... don't know... – Sebastien Lorber Apr 21 '10 at 09:20