Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate doesn't use PostgreSQL sequence to generate primary key

I have a Java Server Faces project using Hibernate to store data into a PostgreSQL database.

The problem I'm having is that Hibernate doesn't take the existing sequence (fifo_id_seq) into consideration while saving the data into the db; it saves with the id = 0;

The answer may be very obvious, as I'm new to Hibernate.

I'm sorry for the tons of code, but I wanted to post everything that may be relevant.

The fifo table:

                                    Table "public.fifo"
       Column        |       Type       |                     Modifiers                     
---------------------+------------------+---------------------------------------------------
 id                  | integer          | not null default nextval('fifo_id_seq'::regclass)
 number_of_processes | integer          | 
 total_time          | integer          | 
 average_time        | double precision | 
 average_wait_time   | double precision | 
 total_wait_time     | integer          | 
Indexes:
"fifo_pkey" PRIMARY KEY, btree (id)

The fifo_id_seq sequence:

         Sequence "public.fifo_id_seq"
    Column     |  Type   |        Value        
---------------+---------+---------------------
 sequence_name | name    | fifo_id_seq
 last_value    | bigint  | 1
 start_value   | bigint  | 1
 increment_by  | bigint  | 1
 max_value     | bigint  | 9223372036854775807
 min_value     | bigint  | 1
 cache_value   | bigint  | 1
 log_cnt       | bigint  | 0
 is_cycled     | boolean | f
 is_called     | boolean | f

FifoEntity.java: *note: constructors and annotations for @Id added by me, the rest is generated

@Entity
@Table(name = "fifo", schema = "public", catalog = "processmanagement")
public class FifoEntity {
private int id;
private Integer numberOfProcesses;
private Integer totalTime;
private Double averageTime;
private Double averageWaitTime;
private Integer totalWaitTime;

public FifoEntity()
{
    // empty
}

public FifoEntity(int numberOfProcesses, int totalTime, double averageTime, double averageWaitTime, int totalWaitTime)
{
    this.numberOfProcesses = numberOfProcesses;
    this.totalTime = totalTime;
    this.averageTime = averageTime;
    this.averageWaitTime = averageWaitTime;
    this.totalWaitTime = totalWaitTime;
}

@Id
@SequenceGenerator(name="fifo_pkey", sequenceName="fifo_id_seq", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator="fifo_pkey")
@Column(name = "id", unique = true, nullable = false)
public int getId() {
    return id;
}

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

@Basic
@Column(name = "number_of_processes")
public Integer getNumberOfProcesses() {
    return numberOfProcesses;
}

public void setNumberOfProcesses(Integer numberOfProcesses) {
    this.numberOfProcesses = numberOfProcesses;
}

@Basic
@Column(name = "total_time")
public Integer getTotalTime() {
    return totalTime;
}

public void setTotalTime(Integer totalTime) {
    this.totalTime = totalTime;
}

@Basic
@Column(name = "average_time")
public Double getAverageTime() {
    return averageTime;
}

public void setAverageTime(Double averageTime) {
    this.averageTime = averageTime;
}

@Basic
@Column(name = "average_wait_time")
public Double getAverageWaitTime() {
    return averageWaitTime;
}

public void setAverageWaitTime(Double averageWaitTime) {
    this.averageWaitTime = averageWaitTime;
}

@Basic
@Column(name = "total_wait_time")
public Integer getTotalWaitTime() {
    return totalWaitTime;
}

public void setTotalWaitTime(Integer totalWaitTime) {
    this.totalWaitTime = totalWaitTime;
}

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    FifoEntity that = (FifoEntity) o;

    if (id != that.id) return false;
    if (averageTime != null ? !averageTime.equals(that.averageTime) : that.averageTime != null) return false;
    if (averageWaitTime != null ? !averageWaitTime.equals(that.averageWaitTime) : that.averageWaitTime != null)
        return false;
    if (numberOfProcesses != null ? !numberOfProcesses.equals(that.numberOfProcesses) : that.numberOfProcesses != null)
        return false;
    if (totalTime != null ? !totalTime.equals(that.totalTime) : that.totalTime != null) return false;
    if (totalWaitTime != null ? !totalWaitTime.equals(that.totalWaitTime) : that.totalWaitTime != null)
        return false;

    return true;
}

@Override
public int hashCode() {
    int result = id;
    result = 31 * result + (numberOfProcesses != null ? numberOfProcesses.hashCode() : 0);
    result = 31 * result + (totalTime != null ? totalTime.hashCode() : 0);
    result = 31 * result + (averageTime != null ? averageTime.hashCode() : 0);
    result = 31 * result + (averageWaitTime != null ? averageWaitTime.hashCode() : 0);
    result = 31 * result + (totalWaitTime != null ? totalWaitTime.hashCode() : 0);
    return result;
}
}

FifoEntity mapped in hbm.xml: *

<class name="com.processmanagement.hibernate.entities.FifoEntity" table="fifo" schema="public" catalog="processmanagement">
    <id name="id" column="id">
        <generator class="sequence-identity">
            <param name="sequence">fifo_id_seq</param>
        </generator>
    </id>
    <property name="numberOfProcesses" column="number_of_processes"/>
    <property name="totalTime" column="total_time"/>
    <property name="averageTime" column="average_time"/>
    <property name="averageWaitTime" column="average_wait_time"/>
    <property name="totalWaitTime" column="total_wait_time"/>
</class>

And this is how I'm trying to save the data into the db using Hibernate:

    FifoEntity fifoEntity = new FifoEntity(processList.size(), totalTime,
            averageProcessTime, averageWaitTime, totalWaitTime);

    databaseHelper.saveOutcomeToDatabase(fifoEntity);
.
.
.
    public void saveOutcomeToDatabase(Object object)
{
//        session.beginTransaction();
//        session.save(object);
//        session.getTransaction().commit();
    Transaction transaction = session.beginTransaction();
    session.persist(object);
    transaction.commit();
    session.clear();
}

Of course, the error when trying to save a consecutive object:

org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "fifo_pkey"
  Detail: Key (id)=(0) already exists.
like image 401
fszuberski Avatar asked Dec 11 '25 05:12

fszuberski


2 Answers

To be able to use sequence on hibernate entity we could use @SequenceGenerator and @Generated value for example :

@Id
@Basic(optional = false)
@Column(name = "id")
@SequenceGenerator(name="third_party_seq", sequenceName="third_party_seq",allocationSize=1)
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="third_party_seq")
private Long id;

I'm using Hibernate and Postgresql. For more reference we could read from this - http://java.dzone.com/articles/hibernate-identity-sequence

like image 139
Sultan Avatar answered Dec 12 '25 19:12

Sultan


you must use GenerationType.IDENTITY if you want use postgresql default SERIAL definition like so:

@Entity
public class Foo {

    @Id
    @GeneratedValue (strategy = GenerationType.IDENTITY)
    private long fooId;

}

One thing to note is that IDENTITY generation disables batch updates as hibernate documentation says.

like image 41
Mohammad Hosein Heidari Avatar answered Dec 12 '25 19:12

Mohammad Hosein Heidari



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!