2

I'm trying to insert mapped object to postgresql database with correct id. This is how i insert:

Session session = Main.getSession();
Transaction rx = session.beginTransaction();
ProductsEntity productsEntity = new ProductsEntity();
productsEntity.setName(nameTextField.getText());
productsEntity.setDescription(descriptionTextArea.getText());
productsEntity.setCategory((ProductCategoriesEntity) categoryComboBox.getSelectedItem());
productsEntity.setPrice(new BigDecimal(1.0));
session.save(productsEntity);
tx.commit();
session.close();

Class with defined sequence:

@Entity
@Table(name = "products", schema = "public", catalog = "shop")
public class ProductsEntity {
    private int id;
    private String name;
    private String description;
    private BigDecimal price;

    @Id
    @Column(name = "id", nullable = false)
    @SequenceGenerator(name="pk_sequence",sequenceName="products_id_seq")
    @GeneratedValue(strategy=GenerationType.AUTO,generator="pk_sequence")
    public int getId() {
        return id;
    }

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

    @Basic
    @Column(name = "name", nullable = false, length = -1)
    public String getName() {
        return name;
    }

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

    @Basic
    @Column(name = "description", nullable = false, length = -1)
    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    @Basic
    @Column(name = "price", nullable = false, precision = 2)
    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }

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

        ProductsEntity that = (ProductsEntity) o;

        if (id != that.id) return false;
        if (name != null ? !name.equals(that.name) : that.name != null) return false;
        if (description != null ? !description.equals(that.description) : that.description != null) return false;
        if (price != null ? !price.equals(that.price) : that.price != null) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = id;
        result = 31 * result + (name != null ? name.hashCode() : 0);
        result = 31 * result + (description != null ? description.hashCode() : 0);
        result = 31 * result + (price != null ? price.hashCode() : 0);
        return result;
    }

    private ProductCategoriesEntity category;

    @ManyToOne
    public ProductCategoriesEntity getCategory() {
        return category;
    }

    public void setCategory(ProductCategoriesEntity category) {
        this.category = category;
    }
}

Last value of postgresql sequence products_id_seq is 4. Hibernate is inserting object with id=0, so first insert was successful, now I'm getting unique constraint violation.

EDIT I've made sequence work by adding generator

<generator class="identity"/>

in xml mapping definition

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="entities.ProductsEntity" table="products" schema="public" catalog="shop">
        <id name="id">
            <column name="id" sql-type="integer"/>
            <generator class="identity"/>
        </id>
        <property name="name">
            <column name="name" sql-type="varchar"/>
        </property>
        <property name="description">
            <column name="description" sql-type="varchar"/>
        </property>
        <property name="price">
            <column name="price" sql-type="numeric(9,2)" precision="9" scale="2"/>
        </property>
        <many-to-one name="category" column="category_id" class="entities.ProductCategoriesEntity" lazy="false"/>
    </class>
</hibernate-mapping>

This works without defining sequence in class. I've also tried to use

@GeneratedValue(strategy=GenerationType.IDENTITY)

in class file but it doesn't work.

If someone has an idea please tell me why only "xml" method works.

dawidmt
  • 33
  • 5
  • Are you generating the table with Hibernate or manually through a console? That does make a difference for the `SequenceGenerator` annotation. – coladict Jan 16 '17 at 08:34
  • @coladict table with sequence is created manually and class with xml are generated by inteliij ide – dawidmt Jan 17 '17 at 13:48
  • When using `@SequenceGenerator` it's `allocationSize` must match the increment value of your sequence. The default `allocationSize` is 50, the default increment size is 1, so that causes it to try inserting duplicate IDs. However if the column takes it's default value from the sequence, there is no reason for `@GeneratedValue(strategy=GenerationType.IDENTITY)` not to work. – coladict Jan 17 '17 at 14:21

1 Answers1

0

Is the sequence "products_id_seq" a DB Sequence?

If Yes, then change your GenerationType from Auto to SEQUENCE.
I've a similar setup with Postgres and setting GenerationType as SEQUENCE and giving allocationSize = 1 worked for me.

Also, ensure your sequence is upto date with the table. If not, Alter the sequence for now so your further updates will not fail.

Community
  • 1
  • 1
Kishore Bandi
  • 5,537
  • 2
  • 31
  • 52