Hibernate - why put a column name before getter instead of variable? - java

If we make a column Id which corresponds to id of User, then why don't we put it near the variable id instead of the getter for id ? I got the answer to that here - Where to put hibernate annotations?.
But, because my book put it near the getter, it looks like some class will need to access this object via getter to serialize/persist it to a database. What is this class and how is does it perform the persistence ? Do I call its methods to do the persistence ?
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
#Entity
public class User {
private Long id;
private String password;
#Id
#GeneratedValue
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}

Hibernate will use reflection to find the appropriate methods or fields on your class to read. This is why Hibernate is able to read private fields.
The code that does this reflection is called from session.save(Object object).

Related

Hibernate error column0_.id does not exist

I have a model class that is mapped to a postgres database using hibernate. My model class is:
CheckRes.java
package com.example.demo.model;
import javax.persistence.Id;
import javax.persistence.*;
#Entity
#Table(name="checkers",schema = "public")
public class CheckRes {
public long getID() {
return ID;
}
public void setID(long ID) {
this.ID = ID;
}
public String getCheck() {
return check;
}
public CheckRes() {
}
public void setCheck(String check) {
this.check = check;
}
#Id
private long ID;
public CheckRes(String check) {
this.check = check;
}
#Column(name="check")
private String check;
}
application.properties
spring.jpa.hibernate.naming_strategy=org.hibernate.cfg.EJB3NamingStrategy
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQL9Dialect
spring.jpa.hibernate.ddl-auto = update
The following table is already existing in db with create script as:
CREATE TABLE public."checkers"
(
"ID" bigint NOT NULL,
"check" character varying(20),
CONSTRAINT "checkers_pkey" PRIMARY KEY ("ID")
)
TABLESPACE pg_default;
ALTER TABLE public."checkers"
OWNER to postgres;
Later when I am trying to invoke the controller get method from a postman , I am getting the following error.
org.postgresql.util.PSQLException: ERROR: column checkres0_.id does not exist
Position: 8
If the table doesnt exist then hibernate automatically creates a table with '_' and there are no errors. But I dont need the hibernate to create any tables. It just needs to use the existing ones for CRUD operations,is there any other naming convention I am missing?
Generally, this is a good practice to follow java naming conventions. According to that you should rename ID field to id.
And then as was noticed by #User-Upvotedon'tsayThanks and #a_horse_with_no_name you should use #Column with quotes:
#Id
#Column(name="`ID`")
private long id;
Also your getters and setters should follow JavaBean conventions. So, for the above field you should have the following getter and setter:
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}

Entity class has no primary key specified

I have an entity class which inherits from four level of inheritance in which the top level parent defines the primary key (#Id) and I'm having trouble figuring out what I did wrong as I get this error:
Entity class [class D] has no primary key specified. It should define either an #Id, #EmbeddedId or an #IdClass. If you have defined PK using any of these annotations then make sure that you do not have mixed access-type (both fields and properties annotated) in your entity class hierarchy.
Here's the hierarchy:
A->B->C->(Entity)D
This is my non-entity class that gives the values to its children:
import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
#MappedSuperclass
public class A implements Serializable {
#Id
#GeneratedValue
protected Long id;
#Temporal(javax.persistence.TemporalType.TIMESTAMP)
protected Date deleted;
public Date getDeleted() {
return deleted;
}
public void setDeleted(Date deleted) {
this.deleted = deleted;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
and this is one of its child :
#MappedSuperclass
public abstract class B extends A implements Serializable {
}
B->C
import javax.persistence.Entity;
import javax.persistence.Transient;
#MappedSuperclass
public class C extends B{
protected String name;
protected String description;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
And finally C-> (Entity)D
#Entity
public class D extends C{
private String codeD;
public String getCodeD(){return codeD;}
public String setCodeD(String codeD) {this.codeD = codeD;}
}
According to every source I've found, normally with the #MappedSuperclass and implementing Serializable it should work. Thought I've tried implementing Serializable even every step of the hierarchy but I received the same error message.
I'm currently using Payara 4.1.1.1621. I don't know if that might be the problem as I've seen this kind of error in Payara on some thread but they all miraculously resolved themselves.
I resolved this error by adding my base class to persistence.xml.
The configuration seems to be as the specification suggests.
The only thing that comes to my mind that can be added is the #Column annotation to explicitly declare the database column names:
#Id
#GeneratedValue
#Column(name = "id")
protected Long id;
#Temporal(javax.persistence.TemporalType.TIMESTAMP)
#Column(name = "deleted")
protected Date deleted;
Try it out. If it still doesnt work try to annotate all the fields in the classes marked as #MappedSuperClass.
Also, class C should have its fields marked as protected not private?

Unable to change revinfo table name in Hibernate Envers

I went to the documentation (http://docs.jboss.org/envers/docs/#revisionlog) there it was written that if we annonate an entity with #RevisionEntity then Hibernate will not create default revinfo table by its own instead it will map the entity which is annotated with #RevisionEntity. I tried still its createing default table named as revinfo and not custom named table as RevisionTable.
Following is the code :
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import org.hibernate.envers.RevisionEntity;
import org.hibernate.envers.RevisionNumber;
import org.hibernate.envers.RevisionTimestamp;
#RevisionEntity
public class RevisionTable {
#Id
#GeneratedValue
#RevisionNumber
private int id;
#RevisionTimestamp
private long timestamp;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
}
I am not understanding where i am going wrong. As i am new to Hibernate Envers, it will be helpfull if explain the solution in detail.
Your revision entity needs to also contain these annotations:
#Entity
#Table(name="REVISIONS_TABLE_NAME")
and it needs to be scanned by hibernate like any other entity. Please refer to the documentation, this was specified there: http://docs.jboss.org/envers/docs/

Hibernate insert automatic number in a column

Hello brothers and sisters,
I have a class that keeps userAuthInformatin with authuserid column,username column, and authusertoken column.
I want to insert uuid number in authusertoken column with every insert. I learned about Generated(GenerationTime.INSERT) but i don't know exact way to do this.
package entities;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.Generated;
import org.hibernate.annotations.GenerationTime;
#Entity
#Table(name = "authusers")
public class AuthUser {
#Id
#GeneratedValue
private int authuserid;
#Generated(GenerationTime.INSERT)
#Column(name = "authusertoken")
private long authusertoken;
#Column(name = "username")
private String username;
public int getAuthuserid() {
return authuserid;
}
public void setAuthuserid(int authuserid) {
this.authuserid = authuserid;
}
public long getAuthusertoken() {
return authusertoken;
}
public void setAuthusertoken(long authusertoken) {
this.authusertoken = authusertoken;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
You can simply use the UUID Java class and assign a value to this token field at object creation time:
#Column(name = "authusertoken", columnDefinition = "BINARY(16)")
private UUID authusertoken = UUID.randomUUID();
If the current associated row already has a value, when fetching the Entity, Hibernate will set it using Reflection and override the authusertoken with the row's column value.
If this is a new object, the authusertoken will get a default UUID when the object is instantiated.

PostgreSQL network types in Hibernate

I want to use Postgresql network data type of mac address (macaddr) in Hibernate ORM. How could I map macaddr type to a entity class property? What is the best way of doing so? I never used non standard SQL types in Hibernate
Thx
Mac address is a String. If it's a #OneToOne relationship between the mac address and its user, then you don't have to make an entity class out of simple strings, just include it as a field on whatever entity needs it, like so:
private String macAddress;
If the same mac address is used by multiple entities and you want to reuse the value (normalize), then you'd make an entity like this:
package com.acme.model;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Entity
public class MacAddress implements Serializable {
private static final long serialVersionUID = 1l;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String value;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
I just solve a problem like this,so I insert and get row from DB postgresql 9 successfully. The solution explained completely is in this link network postgres types on hibernate
Because of the mac-address is never totaly validated, there is no Standard-Type in Java. You can use
#ColumnTransformer(read="CAST(mac AS varchar)", write="CAST(? AS macaddr)") String
instead to read/write it as String.

Categories