Hibernate not save Entity to oracle db - java

I made a small crud app using struts2,spring,hibernate with oracle db.
action class add methos is this.
public String addorgs() throws Exception {
t.setAO_CreatedBy("me");
t.setAO_Name("ok");
orgdao.addOrg(t);
// emplist = empdao.showEmployuee();
return SUCCESS;
}
Entity class for test:
#Entity
#Table(name="test")
public class Test {
#Id
#Column(name = "AO_ID")
#SequenceGenerator(name = "SequenceIdGenerator", sequenceName = "SEQ_AT_ORGANISATION",allocationSize=1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SequenceIdGenerator")
private int AO_ID;
#Column(name = "AO_Name")
private String AO_Name;
#Column(name = "AO_CreatedBy")
private String AO_CreatedBy;
public int getAO_ID() {
return AO_ID;
}
public void setAO_ID(int aO_ID) {
AO_ID = aO_ID;
}
public String getAO_Name() {
return AO_Name;
}
public void setAO_Name(String aO_Name) {
AO_Name = aO_Name;
}
public String getAO_CreatedBy() {
return AO_CreatedBy;
}
public void setAO_CreatedBy(String aO_CreatedBy) {
AO_CreatedBy = aO_CreatedBy;
}
}
DAO method :
public void addOrg(Test t) {
//System.out.println("save : "+org);
Session session = null;
session = sessionfactory.openSession();
try {
System.out.println("before save : "+t.getAO_ID());
session.save(t);
System.out.println("after save : "+t.getAO_ID());
} catch (Exception e) {
e.printStackTrace();
}
I didn't get any errors and data is not go to db. I test this code with mysql and it works fine. I think problem is with sequence.
out put is like this.
before save : 0
Hibernate:
select
SEQ_AT_ORGANISATION.nextval
from
dual
after save : 1

Can you try
public void addOrg(Test t) {
//System.out.println("save : "+org);
Session session = sessionfactory.openSession();
Transaction tx;
try {
tx = session.beginTransaction();
session.save(t);
tx.commit();
System.out.println("after save : "+t.getAO_ID());
} catch (Exception e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
}finally {
session.close();
}

Related

how to delete row in spring boot

I write this in my JpaRepository
#Modifying
#Query("DELETE FROM Backlog b WHERE b.code = ?1")
void deleteBacklog(String code);
and this is my method :
#Transactional
#Override
public Integer deleteBacklog(String code) {
try {
backlogRepository.deleteBacklog(code);
return IReturnedValues.DELETE_BACKLOG_SUCCESS;
}catch(Exception e){
return Integer.MAX_VALUE;
}
}
I got this in the console:
Hibernate: delete from backlog where code=?
but when I check my database I still have the row.
How i call my method:
if(code == null || code == "") {
//user exist, check if the code is valid or not
response=ResponseEntity.ok(IReturnedValues.DELETE_BACKLOG_TOKEN_VALIDE);
}else {
//check if exist a backlog with this code
List<Backlog> backlog = backlogMetier.findByCode(code);
if(backlog == null) {
response= ResponseEntity.ok(IReturnedValues.DELETE_BACKLOG_CODE_NOT_EXISTE);
}else if(backlog != null){
try {
//delete the backlog
retour=backlogMetier.deleteBacklog(code);
response= ResponseEntity.ok(retour);
} catch (Exception e) {
return ResponseEntity.ok(responseClassMax);
}
}
}
this is my entity:
#Entity
public class Backlog {
#Id #GeneratedValue
private Long idBacklog;
private String code;
#ManyToOne(fetch=FetchType.LAZY)
private Utilisateur userBacklog;
private Date creationDate;
private String title;
//getters & setters
//constructors
}
And thanks in advance.
#Query(value=""DELETE FROM Backlog b WHERE b.code = :code")
void deleteBacklog(#Param("code") String code);
It seems Query error, try above code.
use this code
#Repository
public interface BookRepository extends CrudRepository<Book, Long> {
long deleteByTitle(String title);
}
test this method
#Test
#Transactional
public void whenDeleteFromDerivedQuery_thenDeletingShouldBeSuccessful() {
long deletedRecords = repository.deleteByTitle("The Hobbit");
assertThat(deletedRecords).isEqualTo(1);
}

Hibernate: Switched HQL query to SQL query, throws exception: java.lang.ClassCastException

In My DaoImpl class I am trying to fetch list of data of Type TBatchEntry(model class)
#Override
public List<TBatchEntry> getBatchListFormQuery(String batchNo) {
session = sessionFactory.openSession();
List<TBatchEntry> batchListFromQuery = new ArrayList<TBatchEntry>();
try {
tx = session.beginTransaction();
batchListFromQuery = session.createSQLQuery("SELECT * FROM pghms.t_batchentry WHERE t_regNo LIKE '2008%'").list();
tx .commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}
return batchListFromQuery;
}
In my Controller class I am trying to print value but it is throwing error in commented line:
List<TBatchEntry> batchListFromQuery = new ArrayList<TBatchEntry>();
try{
batchListFromQuery = adminService.getBatchListFormQuery(batchNo);
}catch(Exception e){
e.printStackTrace();
}
Iterator its = batchListFromQuery.iterator();
while(its.hasNext()){
batchFromQuery = (TBatchEntry) its.next(); //This line thorws error
System.out.println(batchFromQuery.getName());
}
This is my entity class
#Entity
#Table(name="t_batchEntry")
public class TBatchEntry {
#Id
#Column(name="t_regNo")
private String regNo;
#Column(name="t_name")
private String name;
public String getRegNo() {
return regNo;
}
public void setRegNo(String regNo) {
this.regNo = regNo;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
log of tomcat`root cause
java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to com.sv.pghms.model.TBatchEntry
I'd be really thankful, if somebody could help me.
Try this way just change class name and where condition.It is working for me.
Hope so it will work for you.
List<Book> books = this.sf.getCurrentSession().createSQLQuery("select * from Book where book_id > 3")
.addEntity(Book.class)
.list();
for (Book book : books) {
System.out.println("Book Names are :: " + book.getBookName());
}
Why you are catching TBatchEntry into Object class.You can directly catch into TBatchEntry class.
Change Object[] into TBatchEntry Class, because you are selecting all columns from TBatchEntry table right, try below code i think it will work,
1) From Controller,
List batchListFromQuery = new ArrayList<>();
use foreach loop for displaying records
change return type as below :
#Override
public List<TBatchEntry> getBatchListFormQuery(String batchNo) {
session = sessionFactory.openSession();
List<TBatchEntry> batchListFromQuery = new ArrayList<>();
try {
tx = session.beginTransaction();
batchListFromQuery = session.createSQLQuery("SELECT * FROM pghms.t_batchentry WHERE t_regNo LIKE '2008%'").list();
tx .commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}
return batchListFromQuery;
}
After some study I understood the difference between HQL & SQL query in hibernate.
List<TBatchEntry> batchListFromQuery = new ArrayList<TBatchEntry>();
In case of using HQL query:
batchListFromQuery = session.createQuery(sql).list()
In case of using SQL query:
batchListFromQuery = session.createSQLQuery(sql).addEntity(TBatchEntry.class).list();
Difference is:
.addEntity(TBatchEntry.class)

Hibernate SQlite mapping class with iner classes exception The database file is locked (database is locked)

I need to map object with an inner object which has one more inner object or inner array.
From this answer
{
"id":1,
"zip_code":"0001",
"user":{
"data":{
"id":1,
"username":"user",
"email":"user#gmail.com"
}
}
}
If I comment object field and left only zipCode and id all working fine.
StackOverflow says SQLite should have 1 open session
So I set hibernate.connection.pool_size to 1, and in this way it throws
Java/Hibernate - Exception: The internal connection pool has reached its maximum size and no connection is currently available
But it was yesterday. Today I again have "locked exception".
I think a problem in cascade. When hibernate try to save a first MainEntity it should save User, but DB already locked and in a result, it throws the exception.
Even if I right I have no idea how to avoid it. I tried to use MERGE cascade type but it doesn't work in my situation.
Add project to a git repo
https://github.com/JoaoMunozIII/hibernate
More info below.
After this sql queries
Hibernate: select mainentity_.mId, mainentity_.mZipCode as mZipCode2_0_ from main_entity mainentity_ where mainentity_.mId=?
Hibernate: select next_val as id_val from hibernate_sequence
Hibernate: update hibernate_sequence set next_val= ? where next_val=?
I got this exception
[SQLITE_BUSY] The database file is locked (database is locked)
org.hibernate.exception.LockAcquisitionException: error performing isolated work
at dialect.SQLiteDialect$3.convert(SQLiteDialect.java:197)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:97)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcIsolationDelegate.delegateWork(JdbcIsolationDelegate.java:79)
at org.hibernate.id.enhanced.TableStructure$1.getNextValue(TableStructure.java:125)
at org.hibernate.id.enhanced.NoopOptimizer.generate(NoopOptimizer.java:40)
at org.hibernate.id.enhanced.SequenceStyleGenerator.generate(SequenceStyleGenerator.java:412)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:105)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:192)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:177)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:97)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:73)
at org.hibernate.internal.SessionImpl.fireSaveOrUpdate(SessionImpl.java:651)
at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:643)
at org.hibernate.engine.spi.CascadingActions$5.cascade(CascadingActions.java:218)
at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:391)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:316)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:155)
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:104)
at org.hibernate.event.internal.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:414)
at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:252)
at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:182)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:125)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:192)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:177)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:97)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:73)
at org.hibernate.internal.SessionImpl.fireSaveOrUpdate(SessionImpl.java:651)
at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:643)
at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:638)
at DAO.saveEntityDb(DAO.java:16)
at Main.main(Main.java:32)
Caused by: org.sqlite.SQLiteException: [SQLITE_BUSY] The database file is locked (database is locked)
at org.sqlite.core.DB.newSQLException(DB.java:909)
at org.sqlite.core.DB.newSQLException(DB.java:921)
at org.sqlite.core.DB.throwex(DB.java:886)
at org.sqlite.core.DB.exec(DB.java:155)
at org.sqlite.jdbc3.JDBC3Connection.commit(JDBC3Connection.java:174)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcIsolationDelegate.delegateWork(JdbcIsolationDelegate.java:60)
In the project.
I create models:
Main Entity class
#Entity
#Table(name = "main_entity")
public class MainEntityModel {
#Id
private Long mId;
private Long mZipCode;
#OneToOne(cascade = CascadeType.ALL, targetEntity = User.class)
#JoinColumn(name = "id", insertable = false, updatable = false)
private User mUser;
public Long getmId() {
return mId;
}
public void setmId(Long mId) {
this.mId = mId;
}
public Long getmZipCode() {
return mZipCode;
}
public void setmZipCode(Long mZipCode) {
this.mZipCode = mZipCode;
}
public User getmUser() {
return mUser;
}
public void setmUser(User mUser) {
this.mUser = mUser;
}
}
User class
#Entity
#Table(name = "user_data")
public class User {
#OneToOne(cascade = CascadeType.ALL, targetEntity = UserEntity.class)
#JoinColumn(name="mId")
private UserEntity mData;
public UserEntity getData() {
return mData;
}
public void setmData(UserEntity mData) {
this.mData = mData;
}
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
public User() {
}
}
User entity class
#Entity
#Table(name = "user_entity")
public class UserEntity {
#Id
private Long mId;
private String mUsername;
public Long getmId() {
return mId;
}
public void setmId(Long mId) {
this.mId = mId;
}
public String getmUsername() {
return mUsername;
}
public void setmUsername(String mUsername) {
this.mUsername = mUsername;
}
}
Hibernate Util
public class Hibernate {
private static SessionFactory sessionFactory = null;
private static String dbPath = "D:" + File.separator + "temp.db";
public static SessionFactory getSessionFactory() {
System.out.println("factory " + sessionFactory);
if (sessionFactory == null) {
Configuration cfg = new Configuration()
.setProperty("hibernate.connection.driver_class", "org.sqlite.JDBC")
.setProperty("hibernate.dialect", "dialect.SQLiteDialect")
.setProperty("hibernate.connection.pool_size", "1")
.setProperty("hibernate.connection.url", "jdbc:sqlite:" + dbPath)
.setProperty("hibernate.connection.username", "pass")
.setProperty("hibernate.connection.password", "pass")
.setProperty("hibernate.show_sql", "true")
.setProperty("hibernate.format_sql", "false")
.setProperty("hibernate.hbm2ddl.auto", "create-drop")
.setProperty("hibernate.use_sql_comments", "false")
.addAnnotatedClass(MainEntityModel.class)
.addAnnotatedClass(User.class)
.addAnnotatedClass(UserEntity.class);
sessionFactory = cfg.buildSessionFactory();
return sessionFactory;
} else {
return sessionFactory;
}
}
And Main class
public class Main {
static Long userId = 1l;
private static Long entityId = 1l;
private static Long entityZip = 1000l;
private static List<MainEntityModel> mainEntityModelList = new ArrayList();
public static void main(String[] args) {
UserEntity userEntity = new UserEntity();
userEntity.setmId(userId);
userEntity.setmUsername("User Name " + userId++);
User user = new User();
user.setmData(userEntity);
for (int i = 0; i < 5; i++) {
MainEntityModel mainEntityModel = new MainEntityModel();
mainEntityModel.setmId(entityId++);
mainEntityModel.setmUser(user);
mainEntityModel.setmZipCode(entityZip++);
mainEntityModelList.add(mainEntityModel);
}
DAO.saveEntityDb(mainEntityModelList);
System.out.println("saved");
List<MainEntityModel> savedList = DAO.getEntityDb();
for (MainEntityModel entity: savedList) {
System.out.println(entity.getmZipCode() + "\t"
+ entity.getmUser().getData().getmUsername()
);
}
}
}
DAO class
public class DAO {
static final Session session = Hibernate.getSessionFactory().openSession();
public static void saveEntityDb(List<MainEntityModel> entityList){
Transaction tx=null;
try {
tx = session.beginTransaction();
for (MainEntityModel entity : entityList) {
session.saveOrUpdate(entity);
}
session.flush();
tx.commit();
} catch (Exception ex) {
ex.printStackTrace();
tx.rollback();
} finally{
if(session != null) {
session.close();
}
}
}
public static List<MainEntityModel> getEntityDb(){
Session session = Hibernate.getSessionFactory().openSession();
List<MainEntityModel> entityModel = session.createQuery("from MainEntityModel").list();
session.close();
return entityModel;
}
}
Problem: The auto generation of user.id - it mutually locks/concurs with the insert statement.
Problem: After the lock is fixed, we run into NPE's in the output loop
Solution:
Problem
Manually assign user.id and remove #GeneratedValue() annotation. (verified/tested)
Main.java://or somewhere else
...
user.setId(userId);
...
User.java:
...
#Id
//!#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
...
A nice alternative for "somewhere else" is:
User.java:
...
public void setmData(UserEntity mData) {
this.mData = mData;
if(mData == null) {
this.id = null;
} else {
this.id = mData.getmId();
}
}
#Id
//!#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
...
Or: Perist User/UserData in prior/separate transaction. ...like...
"improve" your DAO.java:
public static <T extends Object> void saveEntityDb(T... entityList) {
//local variable!
final Session session = Hibernate.getSessionFactory().openSession();
Transaction tx = null;
try {
if (session.isConnected()) {
tx = session.beginTransaction();
for (T entity : entityList) {
session.saveOrUpdate(entity);
}
session.flush();
tx.commit();
}
} catch (HibernateException ex) {
if (tx != null && tx.getStatus().canRollback()) {
tx.rollback();
}
} finally {
if (session != null) {
session.close();
}
}
}
and use it twice(!):
Main.java:
...
User user = new User();
user.setmData(userEntity);
//do this before...
DAO.saveEntityDb(user);
List<MainEntityModel> mainEntityModelList = ...
//...you do this
DAO.saveEntityDb(mainEntityModelList.toArray(new MainEntityModel[0]));
Problem
get rid of the insertable = false, updatable = false on MainEntityModel's JoinColumn.
...the OneToOne is somewhat strange here (#MainEntityModel) , it works, but rather used as a ManyToOne (5 to 1 ?!)

JPA - Primary key prefix

We have a table where the ID is generated by a trigger -
ID = year+month+sequence
I mapped the table via JPA and I would like to use the same PK generation in my code as well. I tried the following options:
#Id
#SequenceGenerator(name = "assetSeq", sequenceName = "ASSET_SEQ")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "assetSeq")
#Transient
private long id;
and also tried to change the setter
public void setId(long id) {
String finalId=getIdPrefix()+id;
this.id = Long.parseLong(finalId);
}
private String getIdPrefix() {
DateFormat df = new SimpleDateFormat("YYYYMM");
Date today = Calendar.getInstance().getTime();
return df.format(today);
}
but non of them worked. I just want to insert new record in the database and do not want to use the id later. I use Hibernate for JPA
You can do this if you implement custom Hibernate generator. This blog has almost identical example to what you need. I'll post here the code from the blog adjusted to your needs (might not work if you copy-paste it, but it will be close)
public class CustomIdGenerator implements IdentifierGenerator {
public Serializable generate(SessionImplementor session, Object object)
throws HibernateException {
String prefix = getIdPrefix();
Connection connection = session.connection();
try {
PreparedStatement ps = connection
.prepareStatement("SELECT nextval ('ASSET_SEQ') as nextval"); // could be different, depending on database vendor
ResultSet rs = ps.executeQuery();
if (rs.next()) {
int id = rs.getInt("nextval");
String code = prefix + id;
return code;
}
} catch (SQLException e) {
throw new HibernateException(
"Unable to generate ID");
} finally {
if (ps != null) {
try {
ps.close();
} catch (Throwable e) {
// log error, or rethrow exception
}
}
}
return null;
}
private String getIdPrefix() {
DateFormat df = new SimpleDateFormat("YYYYMM");
Date today = Calendar.getInstance().getTime();
return df.format(today);
}
}
#Id
#GenericGenerator(name="seq_id", strategy="my.package.CustomIdGenerator")
#GeneratedValue(generator="seq_id")
// don't put that #Transient here
private long id;
Hope this helps.

hibernate EventListener and stackoverflow error

I recently came across a situation where I have to do some actions when object is deleted through Hibernate session.
I wan't to remove unidirectionl relashonship before an entity is deleted, but the following code results in a stackoverflow exception.
#Component("emsPreListener")
public class IntegrationEntityDeleteListener implements PreDeleteEventListener {
private static final long serialVersionUID = 2245534615822054792L;
#Override
#SuppressWarnings("unchecked")
public boolean onPreDelete(PreDeleteEvent event) {
System.out.println("PRE-DELETE");
Session session = event.getSession();
if (event.getEntity() instanceof Project) {
Transaction transaction = null;
try
{
transaction = session.beginTransaction();
Project project = (Project) event.getEntity();
Criteria criteria = session.createCriteria(ProjectPoll.class);
criteria.add(Restrictions.eq("project", project));
List<ProjectPoll> polls = criteria.list();
if(polls != null) {
for(ProjectPoll projectPoll : polls) {
session.delete(projectPoll);
}
return false;
}
}
catch (Exception exception) {
exception.printStackTrace();
}
finally
{
if(transaction != null) transaction.commit();
}
}
return false;
}
}
This it the only entity with the relashonship.
#Entity
#Table(name = "project_poll")
#PrimaryKeyJoinColumn(name = "poll_id", referencedColumnName = "id")
public class ProjectPoll extends Poll {
private static final long serialVersionUID = -2230614967405436988L;
#ManyToOne(cascade=CascadeType.ALL)
#JoinColumn(name = "project_id")
private Project project;
public Project getProject() {
return project;
}
public void setProject(Project project) {
this.project = project;
}
}
Tnx
You annotated bidirectional relation ProjectPoll.project with cascade=CascadeType.ALL. Removing a projectPoll will remove also a parent (project). This in turn will trigger onPreDelete() once more. Try to remove cascade attribute on bidirectional relation.

Categories

Resources