Java Hibernate Envers UpdateLockingStrategy warning HHH000416 On AuditTable - java

Hi we have a server running with Hibernate the classes are audited with envers.
Like this :
package db.shared;
import interfaces.GuiEditableTable;
import interfaces.ListableEntity;
import interfaces.ShortDescriptable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import javax.persistence.Version;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.envers.AuditTable;
import org.hibernate.envers.Audited;
import common.Identifiable;
import common.Preferences;
import common.entity.EntityConcurrency;
#Entity
#Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
#Audited
#AuditTable(schema=Preferences.SCHEMA_AUDIT, value=Lizenz.CLASS_NAME+Preferences.AUDIT_SUFFIX)
#Table(schema = Preferences.SCHEMA_SHARED, uniqueConstraints = { #UniqueConstraint(columnNames = { Lizenz.PROPERTY_LIZENZ_NAME }), #UniqueConstraint(columnNames = { Lizenz.PROPERTY_LIZENZ_NUMBER }) })
public class Lizenz extends common.entity.AbstractEntity
implements EntityConcurrency, ListableEntity, ShortDescriptable, GuiEditableTable
{
private static final long serialVersionUID = 589201271279697573L;
public static final String CLASS_NAME = "Lizenz";
public static final String PROPERTY_LIZENZ_NAME = "lizenzName";
public static final String PROPERTY_LIZENZ_NUMBER = "lizenzNummer";
public static final String MTM_PROPERTY_NAME = "lizenz";
public static final int LIZENZ_NUMBER_PADDING = 4;
#Id
#Column(name = Identifiable.PROPERTY_ID, columnDefinition = Preferences.DDL_TYPE_ID)
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long ID;
#Version #Column(name = EntityConcurrency.PROPERTY_VERSION)
private long version;
private String lizenzName;
private String logo;
.
.
.
}
At the serverstart there warnings like that:
15:14:49 WARN [org.hibernate.dialect.lock.UpdateLockingStrategy] HHH000416: Write locks via update not supported for non-versioned entities [db.shared.Lizenz_AUD]
15:14:49 WARN [org.hibernate.dialect.lock.UpdateLockingStrategy] HHH000416: Write locks via update not supported for non-versioned entities [db.shared.Lizenz_AUD]
15:14:49 WARN [org.hibernate.dialect.lock.UpdateLockingStrategy] HHH000416: Write locks via update not supported for non-versioned entities [db.shared.Lizenz_AUD]
15:14:49 WARN [org.hibernate.dialect.lock.PessimisticReadUpdateLockingStrategy] HHH000416: Write locks via update not supported for non-versioned entities [db.shared.Lizenz_AUD]
15:14:49 WARN [org.hibernate.dialect.lock.PessimisticWriteUpdateLockingStrategy] HHH000416: Write locks via update not supported for non-versioned entities [db.shared.Lizenz_AUD]
The Problem is that we are only have created the DB-Table for the Audit, we haven't any Audit-Classes. The Classes will be generated at startup, and we haven't found any #audit-Options to suppress these warnings. The Warnings are irrelevant for us because only write an Audit-entry once and never update it, and 5 warnings per class are flooding our log.
We are using hibernate-envers-4.1.10.Final.jar and hibernate-core-4.1.10.Final.jar with java 1.7.
Does anyone have the same problem or know howto fix it.
we are grateful for any Help.

As we can see in source code of hibernate :
public UpdateLockingStrategy(Lockable lockable, LockMode lockMode) {
this.lockable = lockable;
this.lockMode = lockMode;
if (lockMode.lessThan(LockMode.UPGRADE)) {
throw new HibernateException("[" + lockMode + "] not valid for update statement");
}
if (!lockable.isVersioned()) {
log.warn("write locks via update not supported for non-versioned entities [" + lockable.getEntityName() + "]");
this.sql = null;
} else {
this.sql = generateLockString();
}
}
and the document of isVersioned() :
/**
* Determine whether optimistic locking by column is enabled for this
* entity.
*
* #return True if optimistic locking by column (i.e., <version/> or
* <timestamp/>) is enabled; false otherwise.
*/
public boolean isVersioned();
The consequence is if you want to use audit entity and don't give this warning , you should enable optimistic locking by #Version on a column of your entity :)

Related

JPA load entities, but therein in a #OneToMany list, only load specific

Situation:
(using Payara Server)
I have multiple Groups, and each Group has their own specific set of GroupMeetings.
These GroupMeetings are tracked over multiple years.
Each Group contains 100-10000 GroupMeetings.
But usually only the current year's GroupMeetings are queried and used.
Problem:
How can I load all Groups, but only load each Group's GroupMeeting List for a specific interval, for example only the GroupMeetings of 2019? Or, if need be, specific years or ranges, i.e. 2017-2021 etc?
If I simply run a "SELECT *", then with the FetchType.LAZYI will get empty an emtpy List<GroupMeeting>, but as soon as I access it somewhere in the code, all the items will be loaded.
Question:
Whats the best strategy, i.e. somewhat efficient but not overly convoluted?
Is there an easy SQL/JPQL query that I can run with the classes below?
Is there some structural change - especially in the annotations - needed?
Should I consider Criteria API?
Do I have to use two List<GroupMeeting>s, one with the commonly used meetings, the other with the 'old' meetings?
Example:
Here are the two classes:
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinTable;
import javax.persistence.OneToMany;
#Entity
public class Group {
#Id //
#GeneratedValue() //
private long id;
private String name;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true) #JoinTable(name = "group_meetings") //
private final List<GroupMeeting> meetings = new ArrayList<>();
}
and
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
#Entity
public class GroupMeeting {
#Id //
#GeneratedValue() //
private long id;
private String title;
private Date start;
private Date end;
}
You can use Hibernate filters to achieve that, for instance:
#Entity
#FilterDef(name="groupMeetingFilter",
parameters={#ParamDef( name="fromDate", type="date"), #ParamDef(name="toDate", type="date")} )
public class Group {
#Id //
#GeneratedValue() //
private long id;
private String name;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true) #JoinTable(name = "group_meetings")
#Filter(
name = "groupMeetingFilter",
condition="start <= :fromDate and end >= :toDate"
)
private final List<GroupMeeting> meetings = new ArrayList<>();
}
And you need to enable your filter somewhere in your application, just like this:
Session session = HibernateUtil.getSessionFactory().openSession();
Filter filter = session.enableFilter("groupMeetingFilter");
//Define here the dates that you want
filter.setParameter("fromDate", new Date());
filter.setParameter("toDate", new Date());
You could go further with your research and make the filter global available, if you're using Spring for instance, is easier.

Hibernate : Genereting dynamic entity at runtime

I need to create entity based on information from database. Based on database I created string like this :
` package az.com.ds.entity.crudEntity;
import javax.persistence.Table;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Column;
#Table(name = "CMN_SP", schema = "CMN")
#Entity
public class CmnSpEnt {
#Id
private Integer id;
#Column(name = "NAME")
private String name;
} `
Then I created java file based on this string and compiled it at runtime. Everything works perfectly to this step. But when I want to get data based on entity it throws exception as
org.hibernate.hql.internal.ast.QuerySyntaxException: CmnSpEnt is not mapped [Select x from CmnSpEnt x ].
Now I need to map entity for hibernate in order to get data from database. Is there a way to accomplish this?

Hibernate : Unable to execute schema management to JDBC target

I'm really stuck here and I need help, I've been trying to run my application and let hibernate create tables using my java entities, but it keeps raising this exception :
Unable to execute schema management to JDBC target [create table answer (id_answer bigint not null auto_increment, order integer, text varchar(255), question_id_question bigint, primary key (id_answer))]
Says that there is an error in my SQL syntax, even though i didn't write any sql, i let hibernate handle it all.
Below are my classes and configuration:
Answer.java :
package com.sfm.elearn.business.entities;
import java.io.Serializable;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import com.fasterxml.jackson.annotation.JsonIgnore;
#Entity
public class Answer implements Serializable {
#Id #GeneratedValue
private Long idAnswer;
private String text;
private Integer order;
#ManyToOne
#JsonIgnore
private Question question;
public Answer() {
super();
// TODO Auto-generated constructor stub
}
public Answer(String text, Integer order, Question question) {
super();
this.text = text;
this.order = order;
this.question = question;
}
public Long getIdAnswer() {
return idAnswer;
}
public void setIdAnswer(Long idAnswer) {
this.idAnswer = idAnswer;
}
}
This is my configuration :
spring.datasource.url=jdbc:mysql://localhost:3306/ElearningBase
spring.datasource.username=root
spring.datasource.password=654321
spring.datasource.testWhileIdle=true
spring.datasource.validationQuery=SELECT 1
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
EDIT: I found the error , the attribute "order" is a reserved SQL keyword that's what was causing the error, changing the variable's name solved it!
If Hibernate is creating your tables for your then your hibernate.ddl-auto property should be set to 'create' or 'create-drop'. The update option means Hibernate expects your tables to already exist. See: Hibernate hbm2ddl.auto possible values and what they do?

org.h2.jdbc.JdbcSQLException: Column "Id" not found during testing with H2 Database

I have a class that uses a Hibernate session to call a stored procedure via a JPA #NamedNativeQuery using an in memory H2 database for testing (the actual database is MySQL). The stored procedure inserts a record into a database table and then returns that row.
However during testing, on converting to the JPA #Entity, I am seeing an H2 database error: org.h2.jdbc.JdbcSQLException: Column "Id" not found.
I've documented a cut down version of the code below.
As far as I can tell I think it has something to do with the H2 interpretation of the #Id annotation, but don't understand why, so any help would be gratefully appreciated...
NB - I have searched Stack overflow fairly extensively, including the issue relating to the use of double quotes for column specification, but don't think that this relates to my situation...
Table
CREATE TABLE History.Status_Report (
Id INT NOT NULL AUTO_INCREMENT,
Unique_Users INT NOT NULL,
PRIMARY KEY (Id)
);
Stored Procedure
CREATE PROCEDURE History.Status_Reporting(reporting_date DATE)
BEGIN
INSERT INTO history.status_report (Unique_Users) VALUES (10);
SELECT *
 FROM History.Status_Report WHERE Id = LAST_INSERT_ID();
END;
Entity
package com.test;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.NamedNativeQuery;
import javax.persistence.Table;
import java.io.Serializable;
#NamedNativeQuery(name = "callStatusReporting", query = "CALL Status_Reporting(:reporting_date)", resultClass = StatusReportEntity.class)
#Entity
#Table(name = "Status_Report", catalog = "History")
public class StatusReportEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
#Column(name = "Id")
protected Integer id;
#Column(name = "Unique_Users")
protected int uniqueUsers;
public Integer getId() {
return this.id;
}
public int getUniqueUsers() {
return this.uniqueUsers;
}
}
Class under test
package com.test;
import org.hibernate.Query;
import org.hibernate.Session;
public class MyListener {
public StatusReportEntity doRequest(Date reportDate) {
Session session = HibernateUtil.openSession(); // returns a MySQL session or H2 if testing…
try {
Query query = session.getNamedQuery("callStatusReporting").setParameter("reporting_date", reportDate);;
StatusReportEntity statusReportEntity = (StatusReportEntity) query.uniqueResult();
return statusReportEntity;
} catch (Exception e) {
System.err.println(e);
} finally {
session.close();
return null;
}
}
H2 Aliases
To enable testing using H2, There is also a file to specify the necessary aliases:
CREATE SCHEMA IF NOT EXISTS History;
CREATE ALIAS IF NOT EXISTS Status_Reporting FOR "com.test.StoredProcs.statusReporting";
Test Class to be used by Alias
And a test class to return a default result from the SP call:
package com.test;
import com.test.StatusReportEntity;
public class StoredProcs {
public static StatusReportEntity statusReporting(Date reportingDate) {
StatusReportEntity statusReportEntity = StatusReportEntity.builder().withId(1).withUniqueUsers(10).build();
return statusReportEntity;
}
}
Test Class
package com.test;
import com.test.MyListener;
import java.util.Calendar;
import org.junit.Test;
import static org.junit.Assert.*;
public class MyListenerTest {
private MyListener listener;
#Test
public void listenerReturnsLatestData() throws Exception {
MyListener myListener = new MyListener();
assertNotNull(myListener.statusReporting(Calendar.getInstance().getTime()));
}
}
CREATE TABLE PERSON(
PERSON_ID IDENTITY PRIMARY KEY,
GIVEN_NAME VARCHAR(20),
FIRST_NAME VARCHAR(20),MIDDLE_NAME VARCHAR(20),
LAST_NAME VARCHAR(20),TITLE VARCHAR(20),NAME_SUFFIX VARCHAR(20));
The entity class must use any Generation strategy.
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name ="PERSON_ID")
private int personId;

How to use Hibernate #Index annotation properly? [duplicate]

This question already has answers here:
Creating Indexes on DB with Hibernate #Index Annotation
(4 answers)
Closed 7 years ago.
i have a java class used as an entity that has 2 classes that inherit from it. this class has some indices but these indices didn't appear in the database. this is my java super class code
import java.io.Serializable;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import javax.persistence.Version;
import javax.persistence.OneToMany;
import org.hibernate.annotations.GenericGenerator;
#Entity
#Table(name="service", uniqueConstraints = {#UniqueConstraint(columnNames={"name"})})
#org.hibernate.annotations.Table(appliesTo = "service",
indexes = { #Index(name = "service_name", columnNames = { "name" }),
#Index(name = "service_description", columnNames = { "description" }),
#Index(name = "service_accessNumber", columnNames = { "access_number" })
})
public class Service implements Serializable {
#Column(name="access_number",length = 95,nullable=false)
String accessNumber;
#Column(length=80,nullable=false)
String name;
#Column(length=140)
String description;
}
does any one know what is my problem
Note: i have this problem in my all java classes but this is one of them. the code in all class is the same of this
Edit: i build an xml file and put it in a grails project, and when i run this project, database created
Would a single #Table annotation work? I haven't tried it, I guess the Hibernate #Table might be overridden by JPA #Table.
You may also try #Index annotation on the column fields:
public class Service implements Serializable {
#Index(name="service_accessnumber")
#Column(name="access_number",length = 95,nullable=false)
String accessNumber;
#Index(name="service_name")
#Column(length=80,nullable=false)
String name;
#Index(name="service_description")
#Column(length=140)
String description;
}
i have the same problem, but i found it's solution and it works fine with me try it, it may help you
in your DataSource.groovy file in your grails project make sure that under
environment dbCreate is not equal to "update": if it is equal to "update", change
it to "create".
This works fine just try it

Categories