Hibernate not using defined sequence (postgresql) - java

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.

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.

Related

Java ee, JPA 2.1 retruning null

frist of all sorry for my bad english. I am trying to display database (Postgres) rows from one table, and it allways returning null. I am doing project in Java EE using JPA hibernate.
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<persistence-unit name="mesPU">
<class>pl.mes.model.Users</class>
<properties>
<property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver" />
<property name="javax.persistence.jdbc.url" value="jdbc:postgresql://localhost:5432/test" />
<property name="javax.persistence.jdbc.user" value="postgres" />
<property name="javax.persistence.jdbc.password" value="xxxxxx" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.connection.url" value="jdbc:postgresql://localhost:5432/test"/>
<property name="hibernate.connection.driver_class" value="org.postgresql.Driver"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL9Dialect"/>
</properties>
</persistence-unit>
</persistence>
Users entity
package pl.mes.model;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
#Entity
public class Users {
private Integer userId;
private String firstname;
private String secondname;
private String email;
#Id
#Column(name = "userId", nullable = false)
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
#Basic
#Column(name = "firstname", nullable = true)
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
#Basic
#Column(name = "secondname", nullable = true)
public String getSecondname() {
return secondname;
}
public void setSecondname(String secondname) {
this.secondname = secondname;
}
#Basic
#Column(name = "email", nullable = true)
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Users users = (Users) o;
if (userId != null ? !userId.equals(users.userId) : users.userId != null) return false;
if (firstname != null ? !firstname.equals(users.firstname) : users.firstname != null) return false;
if (secondname != null ? !secondname.equals(users.secondname) : users.secondname != null) return false;
if (email != null ? !email.equals(users.email) : users.email != null) return false;
return true;
}
#Override
public int hashCode() {
int result = userId != null ? userId.hashCode() : 0;
result = 31 * result + (firstname != null ? firstname.hashCode() : 0);
result = 31 * result + (secondname != null ? secondname.hashCode() : 0);
result = 31 * result + (email != null ? email.hashCode() : 0);
return result;
}
}
When i use this
select u from Users u
in console output looks like that:
output
DbSOURCE
I would be grateful if someone can help me with this :)
You have specified the URL jdbc:postgresql://localhost:5432/test for the property javax.persistence.jdbc.url. But when I look at the second screenshot, I can not see a database schema named test.
I guess, you are connecting to the wrong database. Maybe a second instance listening at a different port?
Please also remove the Hibernate specific properties that are already specified by JPA standard properties (as stated out in the comments by Billy Frost).

Select and order list by other condition(Criteria inner join hibernate)

Supposing that we create 2 tables with below SQL :
create table Supplier (id int, name VARCHAR, count int);
create table Product (id int, name VARCHAR, description VARCHAR, price double, supplierId int);
Models:
public class Supplier {
private int id;
private String name;
private int count;
public int getId(){ return id;}
public void setId(int id){ this.id = id; }
public String getName(){ return name;}
public void setName(String name){ this.name = name;}
public int getCount() { return count;}
public void setCount(int count) { this.count = count;}
}
AND
public class Product {
private int id;
private String name;
private String description;
private Double price;
private Supplier supplier;
public int getId() { return id;}
public void setId(int id) { this.id = id; }
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; }
public Double getPrice() {return price;}
public void setPrice(Double price) { this.price = price;}
#OneToOne(targetEntity=ProductAssignment.class, mappedBy = "supplierId", fetch = FetchType.LAZY)
public Supplier getSupplier() { return supplier;}
public void setSupplier(Supplier supplier) { this.supplier = supplier; }
}
If I want to select all products order by count in supplier I can use the below code :
Criteria crit = session.createCriteria(Product.class);
Criteria critSupplier = crit.createCriteria("supplier");
critSupplier.addOrder(Order.desc("count"));
But now, I want to select all suppliers order by price in Product table.
if I want to use MySQL, the below is the script:
select * from supplier s inner join product p ON s.id = p.supplierId order by p.price
Now I want to transfer this SQL into Hibernate Criteria query in java code?
Please help me in this case?
Here you have a bidirectional relationship between two models: Supplier and Product. It is a bidirectional relationship since you want both the models to be aware of each other, and recollect each other information, based on the link that joins them (supplierId). The relationship is also a one(Supplier)-toMany(Products)
So, first off, you are missing the fact that also Supplier must be aware of the existence of the relationship. You have to express this "awareness" by modifying the Supplier model and add to it the list products:
public class Supplier implements Serializable{
private int id;
private String name;
private int count;
private List<Product> products;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public List<Product> getProducts() {
return products;
}
public void setProducts(List<Product> products) {
this.products = products;
}
#Override
public String toString() {
return "Supplier{" + "name=" + name + '}';
}
The second step is to communicate the ORM(in your case hibernate) the relationship between your two models. Online you can find plenty of documentation that explains this subtle "step" of hibernate. in your case, something like this should do.
Hibernate mapping of Supplier:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.xxx.stackoverflowdb.model.Supplier" table="Supplier">
<id column="id" name="id" type="int">
<generator class="assigned"/>
</id>
<property column="name" name="name" type="string"/>
<property column="count" name="count" type="int"/>
<bag name="products" table="product" inverse="true" lazy="false" fetch="select">
<key>
<column name="id"/>
</key>
<one-to-many class="com.xxx.stackoverflowdb.model.Product"/>
</bag>
</class>
</hibernate-mapping>
Hibernate mapping of Product:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.xxx.stackoverflowdb.model.Product" table="PRODUCT">
<id column="id" name="id" type="int">
<generator class="assigned"/>
</id>
<property column="name" name="name" type="string"/>
<property column="description" name="description" type="string"/>
<property column="price" name="price" type="double"/>
<many-to-one name="supplierId" class="com.xxx.stackoverflowdb.model.Supplier" column="supplierId" insert="false" update="false" lazy="false"/>
</class>
</hibernate-mapping>
As you can see, both mapping files declare the relationship. With this set, you can write the Criteria and have it do the job. Since it now hibernate knows about the relationship, it can help you. I've created a simple tester class that demonstrates it:
public class Tester {
public static void main(String[] args) {
//gets a session, assuming your cg file is in a folder called hibernate_dispatcher
//under classpath
SessionFactory sessionFactory = new Configuration().configure("/hibernate_dispatcher/hibernate.cfg.xml")
.buildSessionFactory();
Session session = sessionFactory.openSession();
//gets a session, assuming your cg file is in a folder called hibernate_dispatcher
//under classpath
//YOUR own query --> gets all products order by count in supplier
Criteria criteria1 = session.createCriteria(Product.class);
criteria1.createAlias("supplierId", "supp");
criteria1.addOrder(Order.desc("supp.count"));
for(Object p:criteria1.list()){
Product nthP=(Product)p;
System.out.println(nthP);
}
//YOUR own query --> gets all products order by count in supplier
//the query you've asked --> gets all products order by price in Product
Criteria criteria2 = session.createCriteria(Supplier.class);
criteria2.createAlias("products", "prod");
criteria2.addOrder(Order.desc("prod.price"));
for(Object s:criteria2.list()){
Supplier nthS=(Supplier)s;
System.out.println(nthS);
}
//the query you've asked --> gets all products order by price in Product
}
}

How to map an entity with JPA?

I have a table called fund, I would like to use JPA in order to write my own queries for it. So, I have use IntelliJ to generate persistence mapping based on my schema and not based on hibernate.
import javax.persistence.*;
import java.sql.Timestamp;
#Entity
#Table(name = "fund", schema = "public", catalog = "db")
public class FundEntity {
private long fundId;
private Timestamp createdAt;
private String description;
private Timestamp modTime;
private String modUser;
private String fundName;
private String fundType;
#Id
#Column(name = "fund_id")
public long getFundId() {
return fundId;
}
public void setFundId(long fundId) {
this.fundId = fundId;
}
#Basic
#Column(name = "created_at")
public Timestamp getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Timestamp createdAt) {
this.createdAt = createdAt;
}
#Basic
#Column(name = "description")
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
#Basic
#Column(name = "mod_time")
public Timestamp getModTime() {
return modTime;
}
public void setModTime(Timestamp modTime) {
this.modTime = modTime;
}
#Basic
#Column(name = "mod_user")
public String getModUser() {
return modUser;
}
public void setModUser(String modUser) {
this.modUser = modUser;
}
#Basic
#Column(name = "fund_name")
public String getFundName() {
return fundName;
}
public void setFundName(String fundName) {
this.fundName = fundName;
}
#Basic
#Column(name = "fund_type")
public String getFundType() {
return fundType;
}
public void setFundType(String fundType) {
this.fundType = fundType;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
FundEntity that = (FundEntity) o;
if (fundId != that.fundId) return false;
if (createdAt != null ? !createdAt.equals(that.createdAt) : that.createdAt != null) return false;
if (description != null ? !description.equals(that.description) : that.description != null) return false;
if (modTime != null ? !modTime.equals(that.modTime) : that.modTime != null) return false;
if (modUser != null ? !modUser.equals(that.modUser) : that.modUser != null) return false;
if (fundName != null ? !fundName.equals(that.fundName) : that.fundName != null) return false;
if (fundType != null ? !fundType.equals(that.fundType) : that.fundType != null) return false;
return true;
}
#Override
public int hashCode() {
int result = (int) (fundId ^ (fundId >>> 32));
result = 31 * result + (createdAt != null ? createdAt.hashCode() : 0);
result = 31 * result + (description != null ? description.hashCode() : 0);
result = 31 * result + (modTime != null ? modTime.hashCode() : 0);
result = 31 * result + (modUser != null ? modUser.hashCode() : 0);
result = 31 * result + (fundName != null ? fundName.hashCode() : 0);
result = 31 * result + (fundType != null ? fundType.hashCode() : 0);
return result;
}
}
And this is my persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence-unit name="postgres">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.connection.url" value="jdbc:postgresql://localhost:5443/db" />
<property name="hibernate.connection.driver_class" value="org.postgresql.Driver" />
<property name="hibernate.connection.username" value="dba" />
<property name="hibernate.connection.password" value="XXX" />
<property name="hibernate.archive.autodetection" value="class" />
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL9Dialect" />
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.flushMode" value="FLUSH_AUTO" />
<property name="hibernate.hbm2ddl.auto" value="update" />
</properties>
</persistence-unit>
Then I try to fetch my funds but with no results:
jpa-ql> select f from FundEntity f
[2016-06-29 18:01:11] FundEntity is not mapped [select f from FundEntity f]
What am I missing here ? I thought the discovery for my entities would be made automatically since I have specified on my persistence.xml file.
If your #Entity class is not in the same classpath as the persistence.xml file, it will not be automatically loaded. For example -
Is there a way to scan JPA entities not to declare persistent classes in a persistence.xml file?

Configuring JPA to handle HIBERNATE composite-id and key-property

I am trying to find the correct way to convert the below (Hibernate) XML to JPA annotations:
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<class name="TesTEntry" table="RAW_SCORE">
<composite-id mapped="false" unsaved-value="undefined">
<key-property column="SSN" name="ssn" type="string"/>
<key-property column="SUB_TEST_CD" name="subTestCd" type="string"/>
</composite-id>
<property column="TEST_QY" generated="never" lazy="false"
name="testQy" type="java.lang.Short"/>
<property column="SYS_REC" generated="never" lazy="false"
name="sysRec" type="java.util.Date"/>
<property column="SYS_ID" generated="never" lazy="false"
name="sysId" type="java.lang.String"/>
</class>
Since I have two <key-property> I am not sure if I use #Id, or #EmbeddedId
Since I have two I am not sure if I use #Id, or #EmbeddedId
You mean probably IdClass. And it doesn't matter which one you use.
Let us say, you want to use #IdClass:
Define a class for your ID.
Implement equals and hashCode methods
Implement public default constructor
Implement the Serializable interface
Here is an example implementation (equals & hashCode are generated from IDE):
public class TestEntityPK implements Serializable {
private static final long serialVersionUID = -3424067518791080014L;
private String ssn;
private String subTestCd;
public TestEntityPK() { // }
public TestEntityPK(String ssn, String subTestCd) {
this.ssn = ssn;
this.subTestCd;
}
public String getSsn() {
return ssn;
}
public String getSubTestCd() {
return subTestCd;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((ssn == null) ? 0 : ssn.hashCode());
result = prime * result
+ ((subTestCd == null) ? 0 : subTestCd.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
TestEntityPK other = (TestEntityPK) obj;
if (ssn == null) {
if (other.ssn != null)
return false;
} else if (!ssn.equals(other.ssn))
return false;
if (subTestCd == null) {
if (other.subTestCd != null)
return false;
} else if (!subTestCd.equals(other.subTestCd))
return false;
return true;
}
}
And use it in the entity as follows:
#Entity
#Table(name="RAW_SCORE")
#IdClass(TestEntityPK.class)
public class TestEntity {
#Id private String ssn;
#Id
#Column(name="SUB_TEST_CD")
private String subTestCd;
#Column(name="TEST_QY")
private short testQy;
#Column(name="SYS_REC")
#Temporal(TemporalType.DATE)
private Date sysRec;
#Column(name="SYS_ID")
private String sysId;
// getters and setters
}

Hibernate Composite Primary Key Issue while Saving entity Object

I am trying to save entity using hibernate, But somehow not able to see the record in database table, there is no exception is generated.
My Table, Class and hbm.xml file mapping are as follow.
Table : Table has composite primary key as id and mobile columns.
CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT ,
`mobile` varchar(10) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`name` varchar(40) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
PRIMARY KEY (`id`,`mobile`)
);
Classes :
public class StudentPk implements Serializable {
private Integer id;
private String mobile;
public StudentPk() {
super();
}
public StudentPk(Integer id, String mobile) {
super();
this.id = id;
this.mobile = mobile;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((mobile == null) ? 0 : mobile.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
StudentPk other = (StudentPk) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (mobile == null) {
if (other.mobile != null)
return false;
} else if (!mobile.equals(other.mobile))
return false;
return true;
}
}
class Student{
private StudentPk pk;
private String name;
--getter-setter-
}
Hibernate Mapping :
<class name="com.Student" table="student" proxy="com.Student">
<composite-id name="id" class="com.StudentPk" >
<key-property name="id" type="java.lang.Integer" column ="id"/>
<key-property name="mobile" type="string" column ="mobile" />
</composite-id>
<property name="name" column="name" type="string" />
</class>
I have also map this hbm.xml file in hibernate.cfg.xml file too.
Please help me for this.
The are few rules you have to keep in mind when writing Primary key class:
The primary key class must be public and must have a public no-arg constructor.
The primary key class must be serializable.
The primary key class must define equals and hashCode methods.

Categories

Resources