Well, i have a problem with the @Id @GeneratedValue annotations (i guess).
Below you have all (i guess) necessary data. The issue is quite simple: i am trying to insert several times the same users (not same id, just same name and nickname) in the database using the persistent class outlined below. But, what i get when i want to insert a user with the same name and nickname twice or more times i get a org.hibernate.exception.ConstraintViolationException. I am pretty sure that it is due to this next hibernate generated sql:
insert into appuser (lastname, midname, name, nickname, passwd, iduser) values (, , gcomesana, haleboppp, pw, 20)
iduser is pk for users table in Postgres 8.1, with datatype serial (which means the database generates the id sequences as integers). what i dont understand is, if i tell hibernate the id is a generatedvalue, as you can see below, why hibernate generates a number for the id in that insert statement? does hibernate know the DB sequence or it generates its own sequences? i am confusing with this issue because i though the insert statement shouldn't have the id field, similar to what i have done hundreds of times manually via jdbc...
well, i would appreciate any help, ideas...
please check the configuration as follows and sorry if something is wrong or missing
thanks in advance
Hibernate version: hibernate 3.2.6, hibernate annotations 3.3.0
Mapping documents: well, as you can see below, i am using annotations in persistent classes:
Code:
@Entity
@Table (name="appuser")
public class User {
@Id @GeneratedValue(strategy=GenerationType.AUTO)
@Column (name="iduser")
private Integer id;
@Column (name="name")
private String name;
@Column (name="midname")
private String midname;
@Column (name="lastname")
private String lastname;
@Column (name="nickname")
private String nickname;
@Column (name="passwd")
private String passwd;
@OneToMany (mappedBy="user")
private Set<UserRole> userRole;
public User () {
name = "";
midname = "";
lastname = "";
nickname = "";
passwd = "";
}
private void setId (int id) {
this.id = id;
}
public int getId () {
return id;
}
/*... more getters setters in between... */
public void setNickname (String nick) {
this.nickname = nick;
}
public String getNickname () {
return nickname;
}
}
and the hibernate.cfg.xml is as follows:
Code:
<!DOCTYPE hibernate-configuration SYSTEM "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Don't forget to copy your JDBC driver to the lib/ directory! -->
<!-- Settings for a local PostgreSQL database. -->
<property name="dialect">org.hibernate.dialect.PostgreSQLDialect</property>
<property name="query.substitutions">yes 'Y', no 'N'</property>
<property name="connection.driver_class">org.postgresql.Driver</property>
<!-- <property name="connection.url">jdbc:postgresql://localhost:5432/bcnsap</property> -->
<property name="connection.url">jdbc:postgresql://localhost:5432/appform</property>
<property name="connection.username">postgres</property>
<property name="connection.password">postgres</property>
<!-- Use the C3P0 connection pool provider -->
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.c3p0.timeout">300</property>
<property name="hibernate.c3p0.max_statements">50</property>
<property name="hibernate.c3p0.idle_test_period">3000</property>
<!-- Use the Hibernate built-in pool for tests. -->
<property name="connection.pool_size">3</property>
<!-- Enable auto-commit mode for special cases (integration testing) -->
<property name="connection.autocommit">true</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<property name="cache.use_query_cache">false</property>
<property name="cache.use_minimal_puts">false</property>
<!-- In eager fetching, only join three tables deep if joins are used -->
<property name="max_fetch_depth">3</property>
<!-- Print SQL to stdout, format it nicely -->
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<property name="use_sql_comments">true</property>
<!-- Drop and then re-create schema on SessionFactory build, for testing -->
<property name="hbm2ddl.auto">create</property>
<!-- Use thread-bound persistence context propagation, scoped to the transaction -->
<property name="current_session_context_class">thread</property>
<!-- Application mapping classes/tables -->
<!-- CaveatEmptor annotated EJB3 entity beans.
Use this with the CaveatEmptor.JPA package if you don't want
persistence.xml but hibernate.cfg.xml. Startup with the SessionFactory
instead of the Persistence/EntityManagerFactory bootstrap.
<mapping package="auction.persistence"/>
<mapping class="auction.persistence.audit.AuditLogRecord"/>
<mapping class="auction.model.User"/>
<mapping class="auction.model.Item"/>
<mapping class="auction.model.Category"/>
<mapping class="auction.model.CategorizedItem"/>
<mapping class="auction.model.Bid"/>
<mapping class="auction.model.BillingDetails"/>
<mapping class="auction.model.CreditCard"/>
<mapping class="auction.model.BankAccount"/>
<mapping class="auction.model.Comment"/>
<mapping class="auction.model.AddressEntity"/>
<mapping class="auction.model.Shipment"/>
<mapping resource="auction/model/DynamicModel.hbm.xml"/>
-
<mapping class="org.cnio.pangenes.bean.Patient"/>
<mapping class="org.cnio.pangenes.bean.Phone"/>
-->
</session-factory>
</hibernate-configuration>
Code between sessionFactory.openSession() and session.close():Code:
AnnotationConfiguration cfg = new AnnotationConfiguration ();
cfg.addAnnotatedClass(org.cnio.appform.entity.User.class);
cfg.addAnnotatedClass(org.cnio.appform.entity.Role.class);
cfg.addAnnotatedClass(org.cnio.appform.entity.UserRole.class);
cfg.configure();
SessionFactory sessionFact = cfg.buildSessionFactory();
Session session = sessionFact.openSession();
Transaction tx = session.beginTransaction();
String myName = "myself";
String nick="haleboppp";
String passwd="pw";
User user = new User ();
user.setName(myName);
user.setNickname(nick);
user.setPasswd(passwd);
session.save(user);
myName = "nmalats";
nick="pangenes";
user = new User ();
user.setName(myName);
user.setNickname(nick);
user.setPasswd(passwd);
session.save(user);
tx.commit(); /* <- here is the exception */
session.close();
Full stack trace of any exception that occurs:Code:
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:71)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:253)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:266)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:167)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
at org.cnio.pangenes.util.TestPersistence.main(TestPersistence.java:80)
Caused by: java.sql.BatchUpdateException: Batch entry 0 /* insert org.cnio.appform.entity.User */ insert into appuser (lastname, midname, name, nickname, passwd, iduser) values (, , gcomesana, haleboppp, pw, 20) was aborted. Call getNextException to see the cause.
at org.postgresql.jdbc2.AbstractJdbc2Statement$BatchResultHandler.handleError(AbstractJdbc2Statement.java:2516)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1325)
... many more
Name and version of the database you are using:
PostgreSQL 8.1
The generated SQL (show_sql=true):