Hibernate GenerationType.Table - java

When using Hibernate GenerationType.Table strategy, do we need to have a table already created in the database for key generation, or can Hibernate create one by itself if no data is provided?
I have searched it on the internet and couldn't find a satisfactory answer.
In my code, when using AUTO type,it selects Table strategy which throws an exception that has something to do with the absence of a table for key generation in MySQL db. Just needed to confirm if it is the expected behaviour.
ERROR
DEBUG - select tbl.next_val from hibernate_sequences tbl where tbl.sequence_name=? for update
ERROR - HHH000351: Could not read or init a hi value
java.sql.SQLSyntaxErrorException: Table 'ifinances.hibernate_sequences' doesn't exist
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:120)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:955)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeQuery(ClientPreparedStatement.java:1005)
at org.hibernate.id.enhanced.TableGenerator.executeQuery(TableGenerator.java:705)
at org.hibernate.id.enhanced.TableGenerator.access$400(TableGenerator.java:132)
at org.hibernate.id.enhanced.TableGenerator$1$1.execute(TableGenerator.java:589)
at org.hibernate.id.enhanced.TableGenerator$1$1.execute(TableGenerator.java:575)
at org.hibernate.jdbc.WorkExecutor.executeReturningWork(WorkExecutor.java:55)
at org.hibernate.jdbc.AbstractReturningWork.accept(AbstractReturningWork.java:34)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcIsolationDelegate.delegateWork(JdbcIsolationDelegate.java:57)
at org.hibernate.id.enhanced.TableGenerator$1.getNextValue(TableGenerator.java:574)
at org.hibernate.id.enhanced.NoopOptimizer.generate(NoopOptimizer.java:40)
at org.hibernate.id.enhanced.TableGenerator.generate(TableGenerator.java:570)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:119)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:191)
at org.hibernate.event.internal.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:38)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:176)
at org.hibernate.event.internal.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:32)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:73)
at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:712)
at org.hibernate.internal.SessionImpl.save(SessionImpl.java:704)
at org.hibernate.internal.SessionImpl.save(SessionImpl.java:699)
at com.infiniteskills.data.Application.main(Application.java:42)
ERROR - Table 'ifinances.hibernate_sequences' doesn't exist
Entity class
#Entity
#Table(name = "BANK")
public class Bank {
#Id
/*
* #GeneratedValue(strategy = GenerationType.AUTO, generator = "native")
*
* #GenericGenerator(name = "native", strategy = "native")
*/
#GeneratedValue(strategy = GenerationType.TABLE)
#Column(name = "BANK_ID")
private Long bankId;
#Column(name = "NAME")
private String name;
#Embedded
private Address address = new Address();
application class
package com.infiniteskills.data;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Calendar;
import java.util.Date;
import org.hibernate.Session;import org.hibernate.type.descriptor.java.LocalDateJavaDescriptor;
import com.infiniteskills.data.entities.Bank;
import com.infiniteskills.data.entities.TimeTest;
import com.infiniteskills.data.entities.User;
public class Application {
public static void main(String[] args) {
Session session = HibernateUtil.getSessionFactory().openSession();
try {
session.getTransaction().begin();
/*
* TimeTest test = new TimeTest(new Date()); session.save(test);
* session.getTransaction().commit();
*
* session.refresh(test);
*
* System.out.println(test);
*/
Bank bank = new Bank();
bank.setName("State Bank");
bank.setAddressLine1("Ranibagh");
bank.setAddressLine2("Haldwani");
bank.setCity("Nainital");
bank.setState("UK");
bank.setZipCode("63139");
bank.setCreatedBy("Vaibhav Pandey");
bank.setLastUpdatedBy("Vaibhav Pandey");
bank.setCreatedDate(LocalDateTime.now());
bank.setLastUpdatedDate(LocalDateTime.now());
bank.setInternational(false);
session.save(bank);
session.getTransaction().commit();

Related

How to correctly use #ContainedIn annotation in Hibernate Search?

I'm using Hibernate with PostgreSQL
and Hibernate Search (5.7.0.Alpha1)
with ElasticSearch (2.4.2).
I have two classes: Book and Author.
A book can have many authors
and an author can author more than one book.
I annotated Book class like this:
import java.util.ArrayList;
import java.util.List;
import javax.persistence.*;
import org.hibernate.search.annotations.*;
#Indexed
#Entity
public class Book implements Record {
#Id
#GeneratedValue(strategy=GenerationType.SEQUENCE)
protected Long id;
#Field
protected String title;
#ManyToMany
#JoinTable(name = "books_authors",
joinColumns = #JoinColumn(name = "book_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(name = "author_id", referencedColumnName = "id"))
#IndexedEmbedded(includeEmbeddedObjectId = true)
protected List<Author> authors = new ArrayList<>();
//constructors, getters and setters
//...
}
The problem is that when an author gets updated
(for example their name changes), the document of the correspoding book
does not change in ElasticSearch.
For example after executing this code:
package com.example.app;
import com.example.app.model.Author;
import com.example.app.model.Book;
import com.example.app.model.Category;
import java.io.IOException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class App
{
public static void main(String[] args) throws IOException
{
SessionFactory sessionFactory = new Configuration().configure()
.buildSessionFactory();
Author author01 = new Author("Author 01");
Book book01 = new Book("Book 01");
book01.addAuthor(author01);
{
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(author01);
session.save(book01);
session.getTransaction().commit();
session.close();
}
author01.setName("Author 02");
{
Session session = sessionFactory.openSession();
session.beginTransaction();
session.saveOrUpdate(author01);
session.getTransaction().commit();
session.close();
}
//without this the app won't end
System.exit(0);
}
}
the author document in ElasticSearch will get updated,
but the book document will not change:
{"_index":"com.example.app.model.author","_type":"com.example.app.model.Author","_id":"2","_score":1,
"_source":{"name":"Author 02"}}
{"_index":"com.example.app.model.book","_type":"com.example.app.model.Book","_id":"3","_score":1,
"_source":{"title":"Elementy","authors":[{"name":"Author 01", "id":"2"}]}}}
I read that for the situations like this I need to use #ContainedIn annotation at the Author side,
so I did. For this reason I needed to add the property authoredBooks, I didn't plan it before.
package com.example.app.model;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.*;
import org.hibernate.search.annotations.*;
#Indexed
#Entity
public class Author {
#Id
#GeneratedValue(strategy=GenerationType.SEQUENCE)
protected long id;
#Field
protected String name;
#ContainedIn
#ManyToMany(mappedBy = "authors")
private List<Book> authoredBooks = new ArrayList<>();
//constructors, getters and setters
//...
}
This however did not change the behaviour of Hibernate Search,
so book document is still not updated.
Could you give some hints on what can I do or check?
I'm using Hibernate with PostgreSQL and Hibernate Search (5.7.0.Alpha1) with ElasticSearch (2.4.2).
First thing to do would be to upgrade to an actual release of Hibernate Search (not an Alpha or Beta), to be sure you're not experiencing a bug that has been solved since.
Apart from that... your initial code only updates one side of the relationship; did you make sure to add a author01.addBook(book01) line after ook01.addAuthor(author01)?

Syntax Error in running a query in hql

I have a mysql table summarized as under:
select * from transaction where workflow_id = 'A'\G
*************************** 1. row ***************************
transfer_id: 2
workflow_id: A
amount: 552
status: FAILED
instrument_type: Type-A
creation_date: 2016-02-29 12:11:05
initiation_date: 2016-02-29 12:43:23
completion_date: 2016-02-29 12:43:23
*************************** 2. row ***************************
transfer_id: 1
workflow_id: A
amount: 552
status: SUCCESS
instrument_type: Type-B
creation_date: 2016-03-01 10:25:22
initiation_date: 2016-03-01 10:25:23
completion_date: 2016-03-01 10:25:23
last_modified: 2016-03-01 10:25:23
The corresponding model for this transaction is as under:
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import com.limeroad.services.payments.xhr.CreateTransactionRequest;
import com.limeroad.services.payments.xhr.TransactionState;
import com.limeroad.commons.InstrumentType;
#Entity
#Table(name = "transaction")
public class Transaction implements Serializable {
/**
*
*/
private static final long serialVersionUID = 6353431043455994887L;
public Transaction() {
}
#Id
#Column(name = "transfer_id")
private String transferId;
#Column(name = "workflow_id")
private String workflowId;
#Column(name = "amount")
private Double amount;
#Column(name = "status")
private String status;
#Enumerated(EnumType.STRING)
#Column(name = "instrument_type")
private InstrumentType instrumentType;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "creation_date")
private Date creationDate;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "initiation_date")
private Date initiationDate;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "completion_date")
private Date completionDate;
.........
}
I am currently trying to write a query for "given a workflowId, find the transaction having the maximum creation date"
I am using entityManager for writing the hql query.
The corresponding query is:
(ArrayList<Transaction>) entityManager
.createQuery(
"select a from Transaction a, "
+ "( select workflowId, max(creationDate) as maxCreationDate from Transaction t where t.workflowId in :workflowIds group by t.workflowId) as b"
+ " where a.workflowId=b.workflowId and a.creationDate = b.maxCreationDate ")
.setParameter("workflowIds", workflowIds).getResultList();
I get the following error when running this query
java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: ( near line 1, column 71 [select a from com.limeroad.services.payments.dao.model.Transaction a, ( select workflowId, max(creationDate) as maxCreationDate from com.limeroad.services.payments.dao.model.Transaction t where t.workflowId in :workflowIds group by t.workflowId) as b where a.workflowId=b.workflowId and a.creationDate = b.maxCreationDate ]
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1750)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1677)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1683)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:331)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:293)
Please help
In HQL, Subquery as table is not possible.
HQL subqueries can occur only in the select or where clauses. It cannot be put as a table.
please refer this document https://docs.jboss.org/hibernate/orm/4.3/manual/en-US/html/ch16.html#queryhql-subqueries

#OneToMany SQLIntegrityConstraintViolationException error upon insert (Hibernate)

I am having trouble inserting records with a #OneToMany relationship using Hibernate and Spring MVC. I can successfully insert records without adding anything to the #OneToMany collection. However, upon adding a collection record, it fails stating that there is a SQLIntegrityConstraintViolationException.
My current code for the mapping (annotation-style) is as follows:
Contact.java
package mil.navy.navsupbsc.entity;
import java.util.Collection;
import java.util.LinkedHashSet;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Transient;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
#Entity
#Table(name = "CONTACT2")
public class Contact extends Auditable {
public Contact() {
}
// Create with mandatory fields
public Contact(long id, Salutation salutation, String firstName,
String middleInitial, String lastName,
MilitaryCivilianInformation milCivInfo) {
this.setContactId(id);
this.setSalutation(salutation);
this.setFirstName(firstName);
this.setMiddleInitial(middleInitial);
this.setLastName(lastName);
this.setMilitaryCivilianInformation(milCivInfo);
}
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
#SequenceGenerator(name = "CONTACT_SEQ")
#Column(name = "CONTACT_ID")
private Long contactId;
#Fetch(FetchMode.SUBSELECT)
#OneToMany(cascade = { CascadeType.ALL, CascadeType.REMOVE }, mappedBy = "contact", orphanRemoval = true)
private Collection<Email> emails = new LinkedHashSet<Email>();
/**
* #return the emails
*/
public Collection<Email> getEmails() {
for (Email email : emails) {
email.getEmailType();
}
return emails;
}
/**
* #param emails
* the emails to set
*/
public void setEmails(Collection<Email> emails) {
this.emails.clear();
for (Email email : emails) {
this.addEmail(email);
}
}
public void addEmail(Email email) {
email.setContact(this);
this.getEmails().add(email);
}
[...more Getters / Setters and fields]
}
Email.java
package mil.navy.navsupbsc.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import org.codehaus.jackson.annotate.JsonBackReference;
/**
* Implements Auditing Properties
*/
#Entity
#Table(name = "EMAIL")
public class Email extends Auditable {
private static final long serialVersionUID = -4833322552325183301L;
#Id
#GeneratedValue
#SequenceGenerator(name = "EMAIL_SEQ")
#Column(name = "EMAIL_ID")
private long emailId;
#JsonBackReference
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "CONTACT_FK")
private Contact contact;
[More fields]
public Contact getContact() {
return contact;
}
public void setContact(Contact contact) {
this.contact = contact;
}
public long getEmailId() {
return emailId;
}
public void setEmailId(long emailId) {
this.emailId = emailId;
}
[more getters / setters]
}
ContactDAOImpl (I've tried many variations of this with no success)
public void saveContact(Contact contact) {
Session session = sessionFactory.getCurrentSession();
Collection<Email> emailCollection = new LinkedHashSet<Email>();
emailCollection = contact.getEmails();
Contact contactToSave;
long contactId;
if (contact.getContactId() == 0 || contact.getContactId() == null) {
contactToSave = new Contact((long) 0, contact.getSalutation(),
contact.getFirstName(), contact.getMiddleInitial(),
contact.getLastName(),
contact.getMilitaryCivilianInformation());
session.save(contactToSave);
session.flush();
for (Email email : emailCollection) {
// email.setContact(contactToSave);
contactToSave.addEmail(email);
}
session.saveOrUpdate(contactToSave);
session.flush();
session.clear();
}
Any help with this is much appreciated. I had a previous version of this that updated records correctly, but can't seem to work out the Save new records. I also originally used the contact that I passed in from the web service, but I attempted to create a new record in the DAO to eliminate potential problems in the latest variation of my code.
Also, I know that there are many similar questions, but I have tried many of the answers with no success (hence the new question).
Thank you for your help!
UPDATE
I checked to see what ID the data layer returns after the initial save and verified (unsuccessfully) that the same ID was saved in the database. The returned ID is different than the saved ID. For example, the latest save showed the Contact ID as '1129' with the returned contact after the initial save. I did a retrieve from the database with contact ID '1129' - and it successfully returned the contact. After closing the transaction, I viewed the data directly in the database. The database showed '193' as the Contact ID instead of '1129'. Any ideas??
I figured out the issue I was having.
Prior to creating the Hibernate entity definition, I created a sequence and trigger in the database directly. I also specified the same sequence in the entity definition within the JAVA hibernate code. However, my syntax for generating the sequence was not complete.
Since the syntax for generating the sequence was incomplete, the JAVA code was using the default HIBERNATE_SEQUENCE generator, rather than the sequence I created. Hibernate returned the sequence value from HIBERNATE_SEQUENCE (creating the ID prior to the database insert). However, immediately prior to inserting the value into the database, Oracle ran my custom sequence and assigned the Contact ID to the newly generated value.
Consequently, when I tried to add a value to the collection, the Insert statement attempted to use the sequence value generated by Hibernate as the foreign key, rather than the sequence value generated by the database.
In order to ensure that the Hibernate code and database were in sync, I removed the ContactID trigger from the database. Based on another question in StackOverflow (Hibernate and Oracle Sequence), I updated the JAVA Hibernate code for the Contact.java ContactID declaration to:
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "CONTACT_SEQ")
#SequenceGenerator(name = "CONTACT_SEQ", sequenceName = "contact_seq", allocationSize = 1)
#Column(name = "CONTACT_ID")
private Long contactId;
Thankfully this fixed the problem. The JAVA Hibernate code now creates the ID through the sequence I specified. The database then successfully inserts those values into the database!
I was also able to simplify my save to:
public void saveContact(Contact contact) {
Session session = sessionFactory.getCurrentSession();
if (contact.getContactId() == 0 || contact.getContactId() == null) {
session.save(contact);
session.flush();
}
}
I'm sure that I'll need to change it again though to account for updating the contact - probably using saveOrUpdate() instead of save().

Difficulties to use Hibernate in a Spring: Caused by: org.hibernate.AnnotationException: Use of #OneToMany or #ManyToMany targeting an unmapped class:

I am new in Spring ORM and I am trying to implement this Spring+Hibernate tutorial:
http://it4beginners.wordpress.com/2012/10/05/spring-3-and-hibernate-4-for-beginners/
The only difference is that I am not using PostgreSQL but I am using MySql databse, so I have insert the right MySql connector in the pom.xml file and I have change the mainDataSource property in the ApplicationContext.xml configuration file...
The problem is that when I run my App.java class (the main class that contain the main method) I obtain the following error message in the stacktrace:
Caused by: org.hibernate.AnnotationException: Use of #OneToMany or #ManyToMany targeting an unmapped class: org.andrea.myexample.myHibernateSpringExample.entityclasses.ChemicalStructure.occurence[java.lang.Object]
at org.hibernate.cfg.annotations.CollectionBinder.bindManyToManySecondPass(CollectionBinder.java:1057)
at org.hibernate.cfg.annotations.CollectionBinder.bindStarToManySecondPass(CollectionBinder.java:733)
at org.hibernate.cfg.annotations.CollectionBinder$1.secondPass(CollectionBinder.java:668)
at org.hibernate.cfg.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:66)
at org.hibernate.cfg.Configuration.originalSecondPassCompile(Configuration.java:1597)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1355)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1737)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1788)
at org.springframework.orm.hibernate4.LocalSessionFactoryBuilder.buildSessionFactory(LocalSessionFactoryBuilder.java:242)
at org.springframework.orm.hibernate4.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:372)
at org.springframework.orm.hibernate4.LocalSessionFactoryBean.afterPropertiesSet(LocalSessionFactoryBean.java:357)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1514)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1452)
... 12 more
I don't understand where is the problem !!!
This is the code of the class that seems present the problem:
package org.andrea.myexample.myHibernateSpringExample.entityclasses;
import java.io.Serializable;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
#Entity
#Table(name = "chemical_structure")
public class ChemicalStructure implements Serializable {
private Long id;
private String structureKey;
private String structureData;
private Set<Object> occurence;
/**
* #return the id
*/
#Id
#GeneratedValue(strategy = GenerationType.AUTO, generator = "chem_structure_seq_gen")
#SequenceGenerator(name = "chem_structure_seq_gen", sequenceName = "seq_chemical_structure")
#Column(name = "structure_id")
public Long getId() {
return id;
}
/**
* #param id
* the id to set
*/
public void setId(Long id) {
this.id = id;
}
/**
* #return the structureKey
*/
#Column(name = "structure_key", unique = true)
public String getStructureKey() {
return structureKey;
}
/**
* #param structureKey
* the structureKey to set
*/
public void setStructureKey(String structureKey) {
this.structureKey = structureKey;
}
/**
* #return the structureData
*/
#Column(name = "chemical_structure")
public String getStructureData() {
return structureData;
}
/**
* #param structureData
* the structureData to set
*/
public void setStructureData(String structureData) {
this.structureData = structureData;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.chemicalStructure", cascade = CascadeType.ALL)
public Set<Object> getOccurence() {
return occurence;
}
public void setOccurence(Set<Object> occurence) {
this.occurence = occurence;
}
}
Do you have some idea?
Tnx
The reason for that error lies in the fact that you try to map a Set of plain Objects. Object is not a JPA-entity and therefore it cannot be mapped to a relational type.
You'll need to create an entity named Occurence and map it the way you did it with the Set of Objects.
I think the problem is here mappedBy = "pk.chemicalStructure"
Check that you have a ManyToOne relation in this class like:
#ManyToOne
#JoinColumn(name = "chemicalstructure_id", nullable = false)
#ForeignKey(name = "fk_chemicalstructure_id")
private Occurence occurence;
then mappedBy = "occurence"
The error says that this bi directional relation is missing.

Can #TableGenerator save the last used id in the table instead of the next available?

I need to connect to a vendor db and insert customer data. The sequence table used to generate new customer ids stores the last used id (not the next available). I couldn't find anything in the jpa or hibernate docs that would indicate a way to tell hibernate to treat the id in the seq table as last used instead of next available (when using #TableGenerator).
Do I need to write a custom generator that will behave essentially the same as #TableGenerator with the only difference being the way the value in the sequence table is treated?
My Customer entity is defined as follows:
#Entity
public class Customer {
#Id
#TableGenerator(name = "cust_gen", table = "SEQUENCE", pkColumnName = "target",
pkColumnValue = "customer", valueColumnName = "id", allocationSize = 1)
#GeneratedValue(strategy = GenerationType.TABLE, generator = "pat_gen")
public long getCustomer_id() {
return customer_id;
}
public void setCustomer_id(Long id) {
this.customer_id = id;
}
...
}
Thanks!
I had the same problem. Fixed it this way:
Use Hibernate org.hibernate.annotations.GenericGenerator instead of persistance TableGenerator like this:
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import org.hibernate.annotations.GenericGenerator;
#Entity
#Table(name = "name")
public class Name implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.TABLE, generator = "names")
#GenericGenerator(name = "names", strategy = "com.ourpackage.SybaseTableGenerator", parameters = {
#Parameter(name = "table_name", value = "new_key_numbers"),
#Parameter(name = "value_column_name", value = "key_number"),
#Parameter(name = "segment_column_name", value = "name"),
#Parameter(name = "segment_value", value = "names_key") })
#Column(name = "names_id")
private Long id;
And create your own generator (I used name com.ourpackage.SybaseTableGenerator):
import java.io.Serializable;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.id.enhanced.TableGenerator;
#SuppressWarnings("UnusedDeclaration")
public class SybaseTableGenerator extends TableGenerator {
#Override
public synchronized Serializable generate(SessionImplementor session, Object obj) {
return (Long) super.generate(session, obj) + 1;
}
}
A little bit tricky but it works ;)

Categories

Resources