JPA Not persisting an object J2EE - java

I have a legacy app using JEE5 , I add a class "People" and add "by hand" in the database a lot of records (people only has peopleid and a string peopledesc)
If I use the method getAllPeople() I get the list correctly populated, every data is there
But when I try to persist a new record by code using persistPeople(People pep) It just does nothing
The system.out.println shows the description added to the object so the new created object is passed to the method, but it is not persisted in the database :(
No error is shown in the console output.
People.java
#Entity
public class People implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int idpeople;
private String desc;
persistence.xml
<persistence-unit name="PersistenceUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>entities.People</class>
......
PeopleDAOImPL.JAVA
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceUnit;
import residencias.dominio.Renovacion;
#Stateless
public class PeopleDAOImpl implements PeopleDAO {
//EntityManagerFactory emf = Persistence.createEntityManagerFactory("PersistenceUnit");
#PersistenceUnit(unitName="PersistenceUnit")
private EntityManagerFactory emf;
#Override
public void persistPeople(People pep) {
EntityManager em = emf.createEntityManager();
System.out.println("description is :"+pep.getDesc());
em.persist(pep);
}
#Override
public List<People> getAllPeople() {
EntityManager em = emf.createEntityManager();
List<People> results = new ArrayList();
Query queryPrincipal;
try {
queryPrincipal = em.createQuery("SELECT p FROM People p");
results = queryPrincipal.getResultList();
return results;
} catch (Exception e) {
System.out.println(results.size());
return results;
} finally {
if (em != null) {
emf.close();
em.close();
}
}
}

While during the invocation of a query, you are not obliged to be running within a transaction, when you try to persist / update state of an entity you must be running that particular action within a transaction boundary.
In your case you could use following configuration:
#Stateless
#TransactionManagement(TransactionManagementType.CONTAINER)
public class PeopleDAOImpl implements PeopleDAO {
#PersistenceUnit(unitName="PersistenceUnit")
private EntityManagerFactory emf;
#Override
#TransactionAttribute(TransactionAttributeType.REQUIRED)
public void persistPeople(People pep) {
EntityManager em = emf.createEntityManager();
System.out.println("description is :"+pep.getDesc());
em.persist(pep);
}

Related

Generic DAO, Spring, Hibernate

I want to understand how can i implement the generic methods like add, edit, delete and search on my database, i have already made the connection (hibernate) and works fine
I do have this method, that works
Class: GenericDAO
public <T> T save(final T o){
Session session=HibernateUtil.getSessionFactory().openSession();
Transaction trans=session.beginTransaction();
Object object = (T) session.save(o);
trans.commit();
return (T) object;
}
and in Main
GenericDAO gen = new GenericDAO();
gen.save(object);
also i have others methods that i dont know how to use them
Class: GenericDAO
public void delete(final Object object){
Session session=HibernateUtil.getSessionFactory().openSession();
Transaction trans=session.beginTransaction();
session.delete(object);
trans.commit();
}
/***/
public <T> T get(final Class<T> type, final int id){
Session session=HibernateUtil.getSessionFactory().openSession();
Transaction trans=session.beginTransaction();
Object object = (T) session.get(type, id);
trans.commit();
return (T) object;
}
public <T> List<T> getAll(final Class<T> type) {
Session session=HibernateUtil.getSessionFactory().openSession();
Transaction trans=session.beginTransaction();
final Criteria crit = session.createCriteria(type);
List<T> list = crit.list();
trans.commit();
return list;
}
Thank you
I think GenericDAO class is base class. It's not for using directly. Did you check this article ? I checked this article and created a sample project.
Don't repeat the DAO!
Example
GitHub - generic-dao-hibernate sample
For example, you might want to create an API to retrieve all employees list according to MySQL first step example.
Employees table schema is like following:
Base SQL
CREATE TABLE employees (
emp_no INT NOT NULL, -- UNSIGNED AUTO_INCREMENT??
birth_date DATE NOT NULL,
first_name VARCHAR(14) NOT NULL,
last_name VARCHAR(16) NOT NULL,
gender ENUM ('M','F') NOT NULL, -- Enumeration of either 'M' or 'F'
hire_date DATE NOT NULL,
PRIMARY KEY (emp_no) -- Index built automatically on primary-key column
-- INDEX (first_name)
-- INDEX (last_name)
);
O/R Mapping
Hibernate require you to configure mapping object-relation settings. After that, you will enjoy converting object-to-sql and sql-to-object.
Entity class based on SQL
#Entity, #Table, #Id, #Column, #GeneratedValue are from Hibernate
#Data, #NoArgsConstructor are from lombok, it reduces getter/setter code
#XmlRootElement, #XmlAccessorType are from jaxb, you might don't need to use it
#Entity
#Data
#NoArgsConstructor
#Table(name = "employees")
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement
public class Employees implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "emp_no", unique = true)
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer empNo;
#Column(name = "birth_date")
private Date birthDate;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#Column(name = "gender")
#Enumerated(EnumType.STRING)
private Gender gender;
#Column(name = "hire_date")
private Date hireDate;
}
Resource Class for Frontend
You always need to write DAO(Data Access Object) for accessing the database. GenericDAO is a method to reduce boilerplate sources codes.
EmployeesResource class
CRUD operations on WEB API
#create, #read, #update or #delete
should be equivalent with
SQL
INSERT, SELECT, UPDATE and DELETE
You need to identify a record or records with key. In this case, id is sample primary key.
#Path("/employee")
public class EmployeesResource {
static Logger log = LoggerFactory.getLogger(EmployeesResource.class);
#GET
#Produces(MediaType.APPLICATION_JSON)
public List<Employees> index(#BeanParam Employees paramBean) {
EmployeesDao dao = (EmployeesDao) SpringApplicationContext.getBean("employeesDao");
List<Employees> result = dao.read();
System.out.println("Get all employees: size = " + result.size());
return result;
}
#GET
#Path("{id}")
#Produces(MediaType.APPLICATION_JSON)
public Employees show(#PathParam("id") Integer id) {
EmployeesDao dao = (EmployeesDao) SpringApplicationContext.getBean("employeesDao");
System.out.println("Get employees -> id = " + id);
return dao.read(id);
}
#POST
#Consumes(MediaType.APPLICATION_JSON)
public Integer create(Employees obj) {
EmployeesDao dao = (EmployeesDao) SpringApplicationContext.getBean("employeesDao");
return dao.create(obj);
}
#PUT
#Path("{id}")
#Consumes(MediaType.APPLICATION_JSON)
public void update(Employees obj, #PathParam("id") String id) {
EmployeesDao dao = (EmployeesDao) SpringApplicationContext.getBean("employeesDao");
dao.update(obj);
}
#DELETE
#Path("{id}")
public void destroy(#PathParam("id") Integer id) throws Exception {
EmployeesDao dao = (EmployeesDao) SpringApplicationContext.getBean("EmployeesDao");
dao.delete(id);
}
}
GenericDao interface & implementation
Interface ( as is from ibm's post )
According to the post, we can declare dao interface. Then we should implement that interface's methods.
public interface GenericDao<T, PK extends Serializable> {
/** Persist the newInstance object into database */
PK create(T newInstance);
/**
* Retrieve an object that was previously persisted to the database using
* the indicated id as primary key
*/
T read(PK id);
List<T> read();
/** Save changes made to a persistent object. */
void update(T transientObject);
/** Remove an object from persistent storage in the database */
void delete(PK id) throws Exception;
void delete(T persistentObject) throws Exception;
}
Implementation
public class GenericDaoHibernateImpl<T, PK extends Serializable> implements GenericDao<T, PK> {
private Class<T> type;
#Autowired
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public GenericDaoHibernateImpl(Class<T> type) {
this.type = type;
}
// Not showing implementations of getSession() and setSessionFactory()
private Session getSession() {
Session session = sessionFactory.getCurrentSession();
return session;
}
#Transactional(readOnly = false, rollbackFor = RuntimeException.class)
public PK create(T o) {
return (PK) getSession().save(o);
}
#Transactional(readOnly = false, rollbackFor = RuntimeException.class)
public void update(T o) {
getSession().update(o);
}
#Transactional(readOnly = true)
public T read(PK id) {
return (T) getSession().get(type, id);
}
#SuppressWarnings("unchecked")
#Transactional(readOnly = true)
public List<T> read() {
return (List<T>) getSession().createCriteria(type).list();
}
#Transactional(readOnly = false, rollbackFor = RuntimeException.class)
public void delete(PK id) {
T o = getSession().load(type, id);
getSession().delete(o);
}
#Transactional(readOnly = false, rollbackFor = RuntimeException.class)
public void delete(T o) {
getSession().delete(o);
}
If you use only simple CRUD operations in the project, you don't need to append any code for SQL operations. For example, you can create another simple SQL tables like divisions_table or personnel_table with using extends GenericDao<Division, Integer> or extends GenericDao<Personnel, Integer>.
EDIT
To instantiate real dao class related with each table, you need to configure applicationContext.xml and beans.
example
<bean id="employeesDao" parent="abstractDao">
<!-- You need to configure the interface for Dao -->
<property name="proxyInterfaces">
<value>jp.gr.java_conf.hangedman.dao.EmployeesDao</value>
</property>
<property name="target">
<bean parent="abstractDaoTarget">
<constructor-arg>
<value>jp.gr.java_conf.hangedman.models.Employees</value>
</constructor-arg>
</bean>
</property>
</bean>
P.S.
You need to remember this article was written a decade ago. And, you should think seriously about which O/R mapper is really good or not. I think O/R mapper is slightly declining now. Instead of Hibernate, you can find MyBatis , JOOQ
This is one way to implement a hibernate centric generic DAO. It provides basic CRUD operations along with simple search but can be extended to include other generic features.
IGenericDAO interface
public interface IGenericDAO<T extends Serializable> {
T findOne(long id);
List<T> findAll();
void create(T entity);
void update(T entity);
void delete(T entity);
void deleteById(long entityId);
public void setClazz(Class<T> clazzToSet);
}
AbstractTemplateDAO
import java.io.Serializable;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
public abstract class AbstractHibernateDAO<T extends Serializable> implements IGenericDAO<T> {
private Class<T> clazz;
#Autowired
SessionFactory sessionFactory;
public final void setClazz(Class<T> clazzToSet) {
this.clazz = clazzToSet;
}
#Override
public T findOne(long id) {
return (T) getCurrentSession().get(clazz, id);
}
#Override
public List<T> findAll() {
return getCurrentSession().createQuery("from " + clazz.getName(),clazz).getResultList();
}
#Override
public void create(T entity) {
getCurrentSession().persist(entity);
}
#Override
public void update(T entity) {
getCurrentSession().merge(entity);
}
#Override
public void delete(T entity) {
getCurrentSession().delete(entity);
}
#Override
public void deleteById(long entityId) {
T entity = findOne(entityId);
delete(entity);
}
protected final Session getCurrentSession() {
return sessionFactory.getCurrentSession();
}
}
GenericHiberateDAO
Note: the use of scope prototype here. The spring container creates a new instance of the dao on each request.
#Repository
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class GenericHibernateDAO<T extends Serializable> extends AbstractHibernateDAO<T>
implements IGenericDAO<T> {
//
}
Service class
Shows how to use autowire the generic dao in a service class and pass the model class a parameter. Also, do note that this implementation uses #Transactional annotation for spring transaction management.
#Service
public class TestService implements ITestService {
private IGenericDAO<TestModel> dao;
#Autowired
public void setDao(IGenericDAO<TestModel> daoToSet) {
dao = daoToSet;
dao.setClazz(TestModel.class);
}
#Override
#Transactional
public List<TestModel> findAll() {
return dao.findAll();
}
}
App Config
Shows how to set up spring for automatic transaction management using #EnableTransactionManagement
#Configuration
#ComponentScan("com.base-package")
#EnableTransactionManagement
public class AppConfig {
// add hibernate configuration
// add beans
}

Spring JPA / Hibernate transaction force insert instead of update

Edited. Whilst extending the base repository class and adding an insert method would work an more elegant solution appears to be implementing Persistable in the entities. See Possible Solution 2
I'm creating a service using springframework.data.jpa with Hibernate as the ORM using JpaTransactionManager.
following the basis of the tutorial here.
http://www.petrikainulainen.net/spring-data-jpa-tutorial/
My entity repositories extend org.springframework.data.repository.CrudRepository
I'm working with a legacy database which uses meaningful primary keys rather then auto generated id's
This situation shouldn't really occur, but I came across it due to a bug in testing. Order table has a meaningful key of OrderNumber (M000001 etc). The primary key value is generated in code and assigned to the object prior to save. The legacy database does not use auto-generated ID keys.
I have a transaction which is creating a new order. Due to a bug, my code generated an order number which already existed in the database (M000001)
Performing a repository.save caused the existing order to be updated. What I want is to force an Insert and to fail the transaction due to duplicate primary key.
I could create an Insert method in every repository which performs a find prior to performing a save and failing if the row exists. Some entities have composite primary keys with a OrderLinePK object so I can't use the base spring FindOne(ID id) method
Is there a clean way of doing this in spring JPA?
I previously created a test service without jpa repository using spring/Hibernate and my own base repository. I implemented an Insert method and a Save method as follows.
This seemed to work OK.
The save method using getSession().saveOrUpdate gave what I'm experiencing now with an existing row being updated.
The insert method using getSession().save failed with duplicate primary key as I want.
#Override
public Order save(Order bean) {
getSession().saveOrUpdate(bean);
return bean;
}
#Override
public Order insert(Order bean) {
getSession().save(bean);
return bean;
}
Possible solution 1
Based on chapter 1.3.2 of the spring docs here
http://docs.spring.io/spring-data/jpa/docs/1.4.1.RELEASE/reference/html/repositories.html
Probably not the most efficient as we're doing an additional retrieval to check the existence of the row prior to insert, but it's primary key.
Extend the repository to add an insert method in addition to save. This is the first cut.
I'm having to pass the key into the insert as well as the entity. Can I avoid this ?
I don't actually want the data returned. the entitymanager doesn't have an exists method (does exists just do a count(*) to check existence of a row?)
import java.io.Serializable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.NoRepositoryBean;
/**
*
* #author Martins
*/
#NoRepositoryBean
public interface IBaseRepository <T, ID extends Serializable> extends JpaRepository<T, ID> {
void insert(T entity, ID id);
}
Implementation : Custom repository base class.
Note : A custom exception type will be created if I go down this route..
import java.io.Serializable;
import javax.persistence.EntityManager;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import org.springframework.transaction.annotation.Transactional;
public class BaseRepositoryImpl<T, ID extends Serializable>
extends SimpleJpaRepository<T, ID> implements IBaseRepository<T, ID> {
private final EntityManager entityManager;
public BaseRepositoryImpl(Class<T> domainClass, EntityManager em) {
super(domainClass, em);
this.entityManager = em;
}
public BaseRepositoryImpl(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {
super (entityInformation, entityManager);
this.entityManager = entityManager;
}
#Transactional
public void insert(T entity, ID id) {
T exists = entityManager.find(this.getDomainClass(),id);
if (exists == null) {
entityManager.persist(entity);
}
else
throw(new IllegalStateException("duplicate"));
}
}
A custom repository factory bean
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
import javax.persistence.EntityManager;
import java.io.Serializable;
/**
* This factory bean replaces the default implementation of the repository interface
*/
public class BaseRepositoryFactoryBean<R extends JpaRepository<T, I>, T, I extends Serializable>
extends JpaRepositoryFactoryBean<R, T, I> {
protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
return new BaseRepositoryFactory(entityManager);
}
private static class BaseRepositoryFactory<T, I extends Serializable> extends JpaRepositoryFactory {
private EntityManager entityManager;
public BaseRepositoryFactory(EntityManager entityManager) {
super(entityManager);
this.entityManager = entityManager;
}
protected Object getTargetRepository(RepositoryMetadata metadata) {
return new BaseRepositoryImpl<T, I>((Class<T>) metadata.getDomainType(), entityManager);
}
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
// The RepositoryMetadata can be safely ignored, it is used by the JpaRepositoryFactory
//to check for QueryDslJpaRepository's which is out of scope.
return IBaseRepository.class;
}
}
}
Finally wire up the custom repository base class in the configuration
// Define this class as a Spring configuration class
#Configuration
// Enable Spring/jpa transaction management.
#EnableTransactionManagement
#EnableJpaRepositories(basePackages = {"com.savant.test.spring.donorservicejpa.dao.repository"},
repositoryBaseClass = com.savant.test.spring.donorservicejpa.dao.repository.BaseRepositoryImpl.class)
Possible solution 2
Following the suggestion made by patrykos91
Implement the Persistable interface for the entities and override the isNew()
A base entity class to manage the callback methods to set the persisted flag
import java.io.Serializable;
import javax.persistence.MappedSuperclass;
import javax.persistence.PostLoad;
import javax.persistence.PostPersist;
import javax.persistence.PostUpdate;
#MappedSuperclass
public abstract class BaseEntity implements Serializable{
protected transient boolean persisted;
#PostLoad
public void postLoad() {
this.persisted = true;
}
#PostUpdate
public void postUpdate() {
this.persisted = true;
}
#PostPersist
public void postPersist() {
this.persisted = true;
}
}
Then each entity must then implement the isNew() and getID()
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlRootElement;
import org.springframework.data.domain.Persistable;
#Entity
#Table(name = "MTHSEQ")
#XmlRootElement
public class Sequence extends BaseEntity implements Serializable, Persistable<SequencePK> {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected SequencePK sequencePK;
#Column(name = "NEXTSEQ")
private Integer nextseq;
public Sequence() {
}
#Override
public boolean isNew() {
return !persisted;
}
#Override
public SequencePK getId() {
return this.sequencePK;
}
public Sequence(SequencePK sequencePK) {
this.sequencePK = sequencePK;
}
public Sequence(String mthkey, Character centre) {
this.sequencePK = new SequencePK(mthkey, centre);
}
public SequencePK getSequencePK() {
return sequencePK;
}
public void setSequencePK(SequencePK sequencePK) {
this.sequencePK = sequencePK;
}
public Integer getNextseq() {
return nextseq;
}
public void setNextseq(Integer nextseq) {
this.nextseq = nextseq;
}
#Override
public int hashCode() {
int hash = 0;
hash += (sequencePK != null ? sequencePK.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Sequence)) {
return false;
}
Sequence other = (Sequence) object;
if ((this.sequencePK == null && other.sequencePK != null) || (this.sequencePK != null && !this.sequencePK.equals(other.sequencePK))) {
return false;
}
return true;
}
#Override
public String toString() {
return "com.savant.test.spring.donorservice.core.entity.Sequence[ sequencePK=" + sequencePK + " ]";
}
}
It would be nice to abstract out the isNew() but I don't think I can. The getId can't as entities have different Id's, as you can see this one has composite PK.
I never did that before, but a little hack, would maybe do the job.
There is a Persistable interface for the entities. It has a method boolean isNew() that when implemented will be used to "assess" if the Entity is new or not in the database. Base on that decision, EntityManager should decide to call .merge() or .persist() on that entity, after You call .save() from Repository.
Going that way, if You implement isNew() to always return true, the .persist() should be called no mater what, and error should be thrown after.
Correct me If I'm wrong. Unfortunately I can't test it on a live code right now.
Documentation about Persistable: http://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/domain/Persistable.html
Why not create a clone object which clones everything except your primary keys and then save this cloned object.
Since the PK will not be present, an insert happens, instead of an update
Does this help?
Set updatable = false on your PK column definition. Example:
#Id
#GeneratedValue
#Column(name = “id”, updatable = false, nullable = false)
private Long id;
Setting your id non updatable will stop JPA from doing updates on your primary key, so thing about it.
One option that worked for me, although isn't particularly elegant, but is at least very explicit: Define your own insert method on your JpaRepository and then call it from your code.
public interface MyRepository extends JpaRepository<MyRecord, Integer> {
....
#Modifying(clearAutomatically = true)
#Transactional
#Query(value = "INSERT INTO my_table (field1, field2) "
+ "VALUES (:#{#c.field1}, :#{#c.field2})", nativeQuery = true)
public void insert(#Param("c") MyRecord c);
}
And then in the code doing the insert:
final var newRecord = MyRecord.builder()
.field1(...)
....
.build();
try {
myRepository.insert(newRecord);
} catch (DataIntegrityViolationException e) {
....
}

A few questions about Play2 and Hibernate

I am beginner of Hibernate4. I am configured Play 2.2.4 with Hibernate 4.3.6 entitymanager and write a test application. So, I have Entity class Subject.java
package models.entities;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.persistence.Table;
import play.data.validation.Constraints;
#Entity
#Table(name="subjects")
public class Subject {
#Id
#Column(name="sub_pcode")
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
#Column(name="sub_name")
#Constraints.Required
public String name;
public int getId() {
return id;
}
public Subject() {
id = 0;
}
public void save() {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("testPU");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
if (id == 0) {
em.persist(this);
} else {
em.merge(this);
}
em.getTransaction().commit();
em.close();
}
public void delete() {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("testPU");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Subject tmpSubject = em.find(Subject.class, id);
if (tmpSubject != null) {
em.remove(tmpSubject);
}
em.getTransaction().commit();
em.close();
}
public static Subject get(int id) {
Subject result;
EntityManagerFactory emf = Persistence.createEntityManagerFactory("testPU");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
result = em.find(Subject.class, id);
em.getTransaction().commit();
em.close();
return result;
}
#SuppressWarnings("unchecked")
public static List<Subject> fetchAll() {
List<Subject> result = new ArrayList<>();
EntityManagerFactory emf = Persistence.createEntityManagerFactory("testPU");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Query q = em.createQuery("SELECT s FROM Subject s");
result = q.getResultList();
em.getTransaction().commit();
em.close();
return result;
}
}
And controller class Application.java
package controllers;
import models.entities.Subject;
import play.mvc.Controller;
import play.mvc.Result;
import views.html.index;
import views.html.list;
public class Application extends Controller {
public static Result index() {
return ok(index.render("Your new application is ready."));
}
public static Result addSubject() {
Subject s = new Subject();
s.name = "test subject";
s.save();
return ok(list.render(Subject.fetchAll()));
}
public static Result deleteSubject(int id) {
Subject s = Subject.get(id);
if (null != s) {
s.delete();
}
return ok(list.render(Subject.fetchAll()));
}
public static Result updateSubject(int id) {
Subject s = Subject.get(id);
if (null != s) {
s.name = "new subject";
s.save();
}
return ok(list.render(Subject.fetchAll()));
}
}
All I want is to ask a few questions:
Why I can merge entity (in save() method) without attaching, but
if I wand to delete entity (by the delete() method) - I need to
find entity first or I have an exception about deleting detached
entity?
Seems like from controller classess I can use JPA.em() with
#Transactional annotation to simplify work with hibernate. Is any
simplest way to work with hibernate transactions and entitymanagers
from non-controller classess?
If my code bad-styled, can anybody give me good advice about strategy of
hibernate usage and so on?
Best regards. Thanks for your advices and answers.
Your EntityManagerFactory emf should not be created every time. EntityManagerFactory are thread safe and you should use it as static. If create it every time your performance will drop.
Entity should not handle transactions, they are used only to reflect the database data. The correct way of using an Entity would be in a repository/DAO classes.
Why are you doing id = 0; in your constructor? The default is already 0.
Do not open a transaction in a Controller. Controller should handle only what gets in and what gets out of the project. If you add transaction in it you will be adding unnecessary complexity and increasing the coupling of your code. You could use the pattern OpenSessionInView, EJBs Components or Injection/AOP transaction controller.
To delete an entity you will need to attach it first. You could use the getReference method: Entity justId = entityManager.getReference(Entity.class, ID).
Take a look at this material that will help you understand about the JPA basics: http://uaihebert.com/jpa-mini-book-first-steps-and-detailed-concepts/

Why do I get a NullPointerException while trying to begin transaction?

Before I was getting NullPointerException in this line
EntityManager manager = emf.createEntityManager();
but I fixed it by adding one line above
emf = Persistence.createEntityManagerFactory("main");
Now I am getting NullPointerException in this line
transaction.begin();
I can't understand why. I was trying to take it from the try catch block but was getting the same result. Also in the finally I tried to add emf.close(); but the error doesn't get fixed. Also, I include #Named annotation because someone suggested me to do that.
import java.io.Serializable;
import javax.inject.Named;
import javax.inject.Inject;
import java.sql.*;
import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.PersistenceUnit;
import javax.persistence.TypedQuery ;
import javax.transaction.UserTransaction;
import javax.transaction.RollbackException;
import javax.persistence.criteria.*;
import java.util.List;
import java.util.*;
#Named
public class UserManager implements Serializable{
#PersistenceUnit(unitName="main")
private EntityManagerFactory emf;
#Resource
private UserTransaction transaction;
public UserManager() {}
public UserTransaction getTransaction() { return transaction; }
public void setTransaction(UserTransaction transaction) { this.transaction = transaction; }
public void addUser(User v) throws Exception {
emf = Persistence.createEntityManagerFactory("main");
EntityManager manager = emf.createEntityManager();
boolean commit;
try {
transaction.begin();
manager.joinTransaction();
commit = false;
try {
manager.persist(v);
transaction.commit();
commit = true;
}finally {
if(commit==false){
transaction.rollback();
}
}
}finally {
manager.close();
//emf.close();
}
}
#Named("subBean")
#RequestScoped
public class UserBean implements Serializable{
private List<User> users;
private UserManager vm;
private User v;
private int total;
public UserBean() {
this.total= 0;
users = new ArrayList<User>();
vm = new UserManager();
v = new User();
}
public String addUserAction() throws Exception {
vm.addUser(v);
users = getUsers();
return "submit1";
}
//getters and setters
}
As noted in my comment, the problem is that you're creating an instance of UserManager bean manually and CDI cannot inject the variables. This is noted here:
#Named("subBean")
#RequestScoped
public class UserBean implements Serializable{
//variable is just declared...
private UserManager vm;
public UserBean() {
//and here you're initializing it manually...
vm = new UserManager();
}
//rest of your code...
}
Let CDI do its work by injecting the variable:
#Named("subBean")
#RequestScoped
public class UserBean implements Serializable{
//variable is just declared
//and notify CDI it should inject an instance when creating an instance of the client class
#Inject
private UserManager vm;
public UserBean() {
//no need to initialize it ever
//vm = new UserManager();
}
//rest of your code...
}
By doing this, you won't need to create any field that should be injected in your other bean either, which means you don't need to initialize emf field manually:
//this line should be commented as well...
//emf = Persistence.createEntityManagerFactory("main");

use session bean to insert data with JPA

In a servelt, I try to call the session bean method to insert data to database via JPA. The insert process is written in the session bean.
I tried another example, which I select data from DB. The "select" works good. But I have no idea that why insert does not work.
The error information is:
HTTP Status 500
description: The server encountered an internal error () that prevented it from fulfilling this request.
exception: javax.ejb.EJBException
note: The full stack traces of the exception and its root causes are available in the GlassFish Server Open Source Edition 3.0.1 logs.
I think there is something wrong with "tx.commit()", when I comment it then there is no error. But I do not know what the exactly problem.
Here is the bean class
#Stateless
#LocalBean
public class testSession {
public testSession() {
// TODO Auto-generated constructor stub
}
public void insertData(){
EntityManagerFactory emf;
EntityManager em;
//the Entity Class-Category
Category cat=new Category();
//set value
cat.setId(5);
cat.setName("test cat");
//the "test" is the persist unit in persistence.xml
emf=Persistence.createEntityManagerFactory("test");
em=emf.createEntityManager();
EntityTransaction tx=em.getTransaction();
tx.begin();
em.persist(cat);
tx.commit();
em.close();
emf.close();
}
}
In the servlet
#WebServlet("/testServlet")
public class testServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
#EJB
testSession ts;
public testServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter out=response.getWriter();
out.print("<html><body>");
//call the method in the session bean to insert data
ts.insertData();
out.print("</body></html>");
}
}
you need Injection via #PersistenceContext
The EntityManager itself is created by the container using the information in the persistence.xml, so to use it at runtime, we simply need to request it be injected into one of our components. We do this via #PersistenceContext
The #PersistenceContext annotation can be used on any CDI bean, EJB, Servlet, Servlet Listener, Servlet Filter, or JSF ManagedBean. If you don't use an EJB you will need to use a UserTransaction begin and commit transactions manually. A transaction is required for any of the create, update or delete methods of the EntityManager to work.
Example:
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
#Stateless
#LocalBean
public class testSession {
#PersistenceContext(unitName = "MyUNIT_PERSIS_IMPORTANT_View_THE_persistence.XML")
private EntityManager entityManager;
public testSession() {
// TODO Auto-generated constructor stub
}
public void insertData(){
//the Entity Class-Category
Category cat=new Category();
//set value
cat.setId(5);
cat.setName("test cat");
entityManager.persist(cat);
}
}
Reference
http://tomee.apache.org/examples-trunk/injection-of-entitymanager/
I have used maven to this demo
Demo
https://mega.co.nz/#!AxtRVQzB!MdwwOXA1e_VayWgwIdxGdREhd69QDb6la0yT0mLMaKA
to url to of servlet this
http://<HOST>/use-session-bean-to-insert-data-with-jpa/testServlet
SQL create
CREATE TABLE category (
id INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(200),
PRIMARY KEY (id));
Persistence.xml
...
<persistence-unit name="test" transaction-type="JTA">
..
Java Servlet
import com.mycompany.ejb.testSession;
import java.io.IOException;
import java.io.PrintWriter;
import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
* #author I2B Boris
*/
#WebServlet(name = "testServlet", urlPatterns = {"/testServlet"})
public class testServlet extends HttpServlet {
#EJB
testSession ts;
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
PrintWriter out = response.getWriter();
out.print("<html><body>");
//call the method in the session bean to insert data
ts.insertData();
out.print("</body></html>");
}
}
Java EJB
package com.mycompany.ejb;
import com.mycompany.entities.Category;
import javax.ejb.Stateless;
import javax.ejb.LocalBean;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
/**
*
* #author I2B Boris
*/
#Stateless
#LocalBean
public class testSession {
#PersistenceContext(unitName = "test")
private EntityManager entityManager;
public void insertData() {
//the Entity Class-Category
Category cat = new Category();
//set value
cat.setId(5);
cat.setName("test cat");
entityManager.persist(cat);
}
}
Entity
package com.mycompany.entities;
import java.io.Serializable;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement;
/**
*
* #author I2B Boris
*/
#Entity
#Table(name = "category")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Category.findAll", query = "SELECT c FROM Category c"),
#NamedQuery(name = "Category.findById", query = "SELECT c FROM Category c WHERE c.id = :id"),
#NamedQuery(name = "Category.findByName", query = "SELECT c FROM Category c WHERE c.name = :name")})
public class Category implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#NotNull
#Column(name = "id")
private Integer id;
#Size(max = 200)
#Column(name = "name")
private String name;
public Category() {
}
public Category(Integer id) {
this.id = id;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Category)) {
return false;
}
Category other = (Category) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
#Override
public String toString() {
return "com.mycompany.entities.Category[ id=" + id + " ]";
}
}

Categories