I have the following Scenatio:
I have a Hibernate Data Entity Class:
public class Home extends BaseDatabaseEntity {
#Id
private long id;
}
that extends my Base Entity:
public abstract class BaseDatabaseEntity {
public static <T extends BaseDatabaseEntity> T getById(Class<T> clazz, Serializable id) {
Transaction transaction = null;
try {
#Cleanup Session session = HibernateConfigurator.getSessionFactory().openSession();
transaction = session.beginTransaction();
T returner = session.get(clazz, id);
transaction.commit();
return returner;
} catch (Exception e) {
...
}
}
}
To retrieve the Object from my Database, i use:
Home.getById(Home.class, 1);
My Goal is to get rid of the Home.class / don't need it in the constructor
Related
I need to create a single database table to store different changelog/auditing (when something was added, deleted, updated). I want to capture
id (for the event),
user that triggered it,
entity name,
entity id,
timestamp of the event
Through Hibernate inceptor I can able to audit both insertion and updation operation in the audit table but failed to audit the deleted entries.It doesn't throw any error but it gets rolled back somewhere.Can you provide the solution?
The interface is
public interface IAuditLog {
public Long getId();
}
The audit entity class is
#Entity
#Table(name = "auditlog")
public class AuditLog implements java.io.Serializable {
private Long auditLogId;
private String action;
private String detail;
private Date createdDate;
private long entityId;
private String entityName;
...
}
#Entity
#Table(name = "stock")
public class Stock implements java.io.Serializable, IAuditLog {
...
#Override
public Long getId(){
return this.stockId.longValue();
}
}
Interceptor class
public class AuditLogInterceptor extends EmptyInterceptor{
private Set inserts = new HashSet();
private Set updates = new HashSet();
private Set deletes = new HashSet();
#Autowired private static AuditRepo auditRepo;
public boolean onSave(Object entity,Serializable id,
Object[] state,String[] propertyNames,Type[] types)
throws CallbackException {
System.out.println("onSave");
if (entity instanceof IAuditLog){
inserts.add(entity);
}
return false;
}
public boolean onFlushDirty(Object entity,Serializable id,
Object[] currentState,Object[] previousState,
String[] propertyNames,Type[] types)
throws CallbackException {
System.out.println("onFlushDirty");
if (entity instanceof IAuditLog){
updates.add(entity);
}
return false;
}
public void onDelete(Object entity, Serializable id,
Object[] state, String[] propertyNames,
Type[] types) {
System.out.println("onDelete");
if (entity instanceof IAuditLog){
deletes.add(entity);
}
}
//called after committed into database
public void postFlush(Iterator iterator) {
try{
for (Iterator it = inserts.iterator(); it.hasNext();) {
IAuditLog entity = (IAuditLog) it.next();
System.out.println("postFlush - insert");
logIt("Saved",entity);
}
for (Iterator it = updates.iterator(); it.hasNext();) {
IAuditLog entity = (IAuditLog) it.next();
System.out.println("postFlush - update");
logIt("Updated",entity);
}
for (Iterator it = deletes.iterator(); it.hasNext();) {
IAuditLog entity = (IAuditLog) it.next();`enter code here`
System.out.println("postFlush - delete");
logIt("Deleted",entity);
}
} finally {
inserts.clear();
updates.clear();
deletes.clear();
}
}
private void logIt(String action, Object entity) {
try {
...
//setting into auditlog
auditRepo.save(auditLog);
} catch (HibernateException e) {
}
}
}
As part of sequence generation for non-primary key, I am using #GeneratorType on entity field. In generator class I require to know a field on that it has been called. Help is appreciated.
#Entity(name = "student")
public class Student {
#GeneratorType(type = IdGenerator.class, when = GenerationTime.INSERT)
private Integer secId;
}
public class IdGenerator implements ValueGenerator<Integer>{
#Override
public Integer generateValue(Session session, Object owner) {
// I want secId here
}
}
You can try to use something like this:
public interface EntityId {
Integer getId();
}
#Entity(name = "student")
public class Student implements EntityId {
#GeneratorType(type = IdGenerator.class, when = GenerationTime.INSERT)
private Integer secId;
#Override
public Integer getId() {
return secId;
}
// ...
}
#Entity
public class OtherEntity implements EntityId {
// ...
}
public class IdGenerator implements ValueGenerator<Integer> {
#Override
public Integer generateValue(Session session, Object owner) {
if (!(owner instanceof EntityId)) {
throw new IllegalArgumentException("IdGenerator can be used only with entities that implement EntityId interface");
}
// I want secId here
Integer id = ((EntityId) owner).getId();
}
}
If you use Java 14 or higher you can use pattern matching for instanceof as more elegant construction.
public class IdGenerator implements ValueGenerator<Integer> {
#Override
public Integer generateValue(Session session, Object owner) {
if (owner instanceof EntityId entityId) {
// I want secId here
Integer id = entityId.getId();
// ...
} else {
throw new IllegalArgumentException("IdGenerator can be used only with entities that implement EntityId interface");
}
}
}
I have a situation where i need to reset the auto-Increment key to the previous value in case of roll back. I have a series of create statement in my controller class. If any exception occurs I am able to roll back all the create statements. But the the auto-Increment generated doesn't reset for a particular successfully entity. Kindly help
The following is my contoller class.
#EJB
private jpa.session.ClassMasterFacade ejbFacadeCM;
#EJB
private jpa.session.StudentMasterFacade ejbFacadeSM;
#EJB
private jpa.session.ParentsMasterFacade ejbFacadePM;
#EJB
private jpa.session.AddressMasterFacade ejbFacadeAM;
#Resource
UserTransaction tran;
public String confirmData() {
try {
tran.begin();
ejbFacadeSM;.create(selectedSM);
ejbFacadeCM;.create(selectedCM)
ejbFacadeAM;.create(selectedAM);
ejbFacadePM;.create(selectedPM);
} catch (Exception e) {
tran.rollback();
JsfUtil.addErrorMessage(e, ResourceBundle.getBundle ("/resources/Bundle").getString("PersistenceErrorOccured"));
return null;
}
}
Example Facade Class
#Stateless
public class ClassMasterFacade extends AbstractFacade<ClassMaster> {
#PersistenceContext(unitName = "sdjv_smsPU")
private EntityManager em;
#Override
protected EntityManager getEntityManager() {
return em;
}
public ClassMasterFacade() {
super(ClassMaster.class);
}
}
All other facade classes are similar to the above class. The abstract class is:
public abstract class AbstractFacade<T> {
private Class<T> entityClass;
public AbstractFacade(Class<T> entityClass) {
this.entityClass = entityClass;
}
protected abstract EntityManager getEntityManager();
public void create(T entity) {
getEntityManager().persist(entity);
}
public void edit(T entity) {
getEntityManager().merge(entity);
}
public void remove(T entity) {
getEntityManager().remove(getEntityManager().merge(entity));
}
public T find(Object id) {
return getEntityManager().find(entityClass, id);
}
}
The autogenerated key in each enityclass is similar to
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "class_group_id")
private Integer classGroupId;
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();
}
Let's say I have entity A and entity B. Entity A have #OneTomany relationship with B.
I want to persist row in A only if it has one or more child object's associated with it else throw an exception.
How can i achieve the above requirement in hibernate
You neglected to mention what version of Hibernate you are using. In any case, this falls within the purview of validation. Luckily, in both Hibernate 3 and 4 you can utilize Hibernate Validator to do the job:
public class EntityB implements Serializable {
}
public class EntityA implements Serializable {
#NotNull
#Size(min = 1)
private Set<EntityB> relatedEntities;
}
You may need to pull in the Hibernate Validator jars into your project in order to be able to do this.
Entity class:Register.class
public class Register{
private Long regId;
#OneToMany(mappedBy = "reg")
private Set addrSet;
public Set getAddrSet() {
return addrSet;
}
public void setAddrSet(Set<Address> addrSet) {
this.addrSet = addrSet;
}
}
Entity Class:Address.java
public class Address{
object values;
#ManyToOne
private Register reg;
public Register getReg() {
return reg;
}
public void setReg(Register reg) {
this.reg = reg;
}
}
public void class searchObject(){
public List lst;
public register searchRegisterRow(Long regId){
Session session = null;
SessionFactory sessionFactory = null;
register result = null;
try{
sessionFactory = new Configuration().configure().buildSessionFactory();
session =sessionFactory.openSession();
String SQL_QUERY ="from Register r where r.redId = "+regId;
Register reg = session.createQuery(SQL_QUERY);
for(Iterator it=lst.iterator();it.hasNext();){
reg=(Register)it.next();
if(reg.getAddrSet().size() > 0){
result = reg;
}
else{
throw new Exception();
}
}
return result;
}
}catch(Exception e){
System.out.println(e.getMessage());
}finally{
// Actual contact insertion will happen at this step
session.flush();
session.close();
}
}
}
I think you should try above code. this will help you.