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;
Related
I have a really strange sometimes if I load my data with JPA some enetities have null values even if there are values in the database.
The data is not newly created and it's not happening to every record.
The only value which is set is the primary key
I coulnd't find anything similar while researching
AbstarctFacade.java
import java.util.List;
import javax.persistence.EntityManager;
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 void detach(T entity) {
getEntityManager().detach(entity);
}
public T find(Object id) {
return getEntityManager().find(entityClass, id);
}
public List<T> findAll() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
return getEntityManager().createQuery(cq).getResultList();
}
}
ItemFacade.java
import ch.itwork.map.core.util.AbstractFacade;
import javax.ejb.Stateless;
import javax.persistence.Cache;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
#Stateless
public class ItemFacade extends AbstractFacade<Item> {
#PersistenceContext(unitName = "...")
private EntityManager em;
#Override
protected EntityManager getEntityManager() {
em.clear();
Cache cache = em.getEntityManagerFactory().getCache();
cache.evict(Item.class);
return em;
}
public void clearCache() {
em.clear();
Cache cache = em.getEntityManagerFactory().getCache();
cache.evict(Item.class);
}
public ItemFacade() {
super(Item.class);
}
}
This is the call which causes the problem.
getItemFacade().findAll();
I have an entity and would like to implement Audit and AuditHistory, both works but while unit testing Application context is null.
The Entity
#Setter
#Getter
#NoArgsConstructor
#AllArgsConstructor
#Entity
#EntityListeners(UserListener.class)
public class User extends BaseModel<String> {
#Column
private String username;
#Column
private String password;
#Transient
private String passwordConfirm;
#ManyToMany
private Set<Role> roles;
}
UserListener
public class UserListener {
#PrePersist
public void prePersist(User target) {
perform(target, INSERTED);
}
#PreUpdate
public void preUpdate(User target) {
perform(target, UPDATED);
}
#PreRemove
public void preRemove(User target) {
perform(target, DELETED);
}
#Transactional(MANDATORY)
void perform(User target, Action action) {
EntityManager entityManager = BeanUtil.getBean(EntityManager.class);
if(target.isActive()){
entityManager.persist(new UserAuditHistory(target, action));
}else{
entityManager.persist(new UserAuditHistory(target, DELETED));
}
}
}
UserAuditHistory
#Entity
#EntityListeners(AuditingEntityListener.class)
public class UserAuditHistory {
#Id
#GeneratedValue
private Long id;
#ManyToOne
#JoinColumn(name = "user_id", foreignKey = #ForeignKey(name = "FK_user_history"))
private User user;
#CreatedBy
private String modifiedBy;
#CreatedDate
#Temporal(TIMESTAMP)
private Date modifiedDate;
#Enumerated(STRING)
private Action action;
public UserAuditHistory() {
}
public UserAuditHistory(User user, Action action) {
this.user = user;
this.action = action;
}
}
BeanUtil for getting and setting context
#Service
public class BeanUtil implements ApplicationContextAware {
private static ApplicationContext context;
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
public static <T> T getBean(Class<T> beanClass) {
return context.getBean(beanClass);
}
}
Now the Junit where I get null pointer exception on the context from the above BeanUtil class in getBean() method.
#RunWith(SpringRunner.class)
#DataJpaTest
public class UserRepositoryTest{
#Autowired
private TestEntityManager entityManager;
#Autowired
private UserRepository repository;
#Test
public void whenFindAll_theReturnListSize(){
entityManager.persist(new User("jk", "password", "password2", null));
assertEquals(repository.findAll().size(), 1);
}
}
This is how I solved the problem, in the test class
#Autowired
ApplicationContext context;
inside the test method called
BeanUtil beanUtil = new BeanUtil();
beanUtil.setApplicationContext(context);
and it worked.
The problem is, that you're not using spring's AOP, but the static context:
private static ApplicationContext context;
It's null, because not creating #Bean leads to unproxied objects. The solution would be to #Autowire it.
Hello, everybody!
Some time ago I run into a trouble: if save method of repository fails, identifier, injected to a bean by Hibernate, remains in the bean. That behaviour may led us to a situation, when we will think about our not persistent bean as about persistent one. I would be pleased to know what practice is common to avoid this situation.
Example test(spring boot + hibernate + oracle database):
#Entity
#SequenceGenerator(name = "TEST_ENTITY_GENERATOR", allocationSize = 1, sequenceName = "TEST_ENTITY_SEQ")
public class TestEntity {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "TEST_ENTITY_GENERATOR")
private Long id;
#Column(nullable = false)
private String name;
public Long getId() {
return id;
}
}
#Repository
public interface TestEntityRepository extends JpaRepository<TestEntity, Long> {
}
#RunWith(SpringRunner.class)
#SpringBootTest
public class RemainingIdTest {
#Autowired
private TestEntityRepository testEntityRepository;
#Test
public void test() {
TestEntity entity = new TestEntity();
try {
Assertions.assertThat(entity.getId()).isNull();
testEntityRepository.save(entity);
Assertions.fail("Save must fail");
} catch (DataIntegrityViolationException e) {
Assertions.assertThat(entity.getId()).isNotNull();
}
}
}
A possible solution is to use org.hibernate.event.spi.PreInsertEventListener where we can bind the transaction with a processor that will clear your entity if transaction is failed.
Example:
#Component
public class IdentifierCleaner implements PreInsertEventListener {
#Autowired
private EntityManagerFactory entityManagerFactory;
#PostConstruct
private void init() {
SessionFactoryImpl sessionFactory = entityManagerFactory.unwrap(SessionFactoryImpl.class);
EventListenerRegistry registry = sessionFactory.getServiceRegistry().getService(EventListenerRegistry.class);
registry.getEventListenerGroup(EventType.PRE_INSERT).appendListener(this);
}
#Override
public boolean onPreInsert(PreInsertEvent event) {
Object entity = event.getEntity();
event.getSession().getActionQueue().registerProcess(((success, session) -> {
if (!success) {
event.getPersister().resetIdentifier(
entity,
event.getId(),
event.getPersister().getVersion(entity),
event.getSession()
);
}
}));
return false;
}
}
I want suggestion regarding a scenario I've been thinking of doing if possible. Suppose I have some JPA database entity class like:
#Entity
public class Person {
#Column(name = "ID")
private Long id;
#Column(name = "FIRST_NAME")
private String firstName;
#Column(name = "LAST_NAME")
private String lastName;
public String getFirstName(){
return this.firstName;
}
public void setFirstName(String firstName){
this.firstName = firstName;
}
public String getLastName(){
return this.lastName;
}
public void setLastName(String lastName){
this.lastName = lastName;
}
}
I am using EJB services. I can use separate business logic methods to make CRUD operation over these entities. Is it possible to use a generic template CRUD operations for these entity classes? Like if I want to create new person I will provide the Person entity class and fields to set as parameter and my generic method will create a new Person record and will do the same job for Read, Update and Delete operation as well.
Any respective example will be highly appreciated.
Thank You
Using EJB and JPA
You can consider an abstract class for the service layer:
public abstract class AbstractFacade<E extends Serializable,
PK extends Serializable> {
private final transient Class<E> entityClass;
public AbstractFacade(final Class<E> entityClass) {
this.entityClass = entityClass;
}
protected abstract EntityManager getEntityManager();
public void create(final E entity) {
final EntityManager entityManager = getEntityManager();
entityManager.persist(entity);
}
public final E find(final PK id) {
return getEntityManager().find(entityClass, id);
}
// Other common operations
}
And a particular service:
#Stateless
public class PersonFacade extends AbstractFacade<Person, Long> {
#PersistenceContext(unitName = "MyPU")
private EntityManager em;
#Override
protected EntityManager getEntityManager() {
return em;
}
public PersonFacade() {
super(Person.class);
}
// Other methods of this service
}
Using Spring and Hibernate
You could have a abstract base class for common DAO methods.
public abstract class AbstractDAO<E extends Serializable,
PK extends Serializable> {
private final transient Class<E> entityClass;
public AbstractDAO(final Class<E> entityClass) {
this.entityClass = entityClass;
}
protected abstract EntityManager getEntityManager();
public final E find(final PK id) {
return getEntityManager().find(entityClass, id);
}
// Another common methods
}
In every DAO implementation, you can put particular methods for that DAO.
#Repository
public final class PersonDAO extends AbstractDAO<Person, Long> {
#Autowired
private transient EntityManagerFactory emf;
public PersonDAO() {
super(Person.class);
}
#Override
protected EntityManager getEntityManager() {
return emf.createEntityManager();
}
// particular methods for this DAO
}
What about if the user not exists? Put this logic in the service layer.
#Service
public final class PersonService {
private static final Logger LOG = LoggerFactory.getLogger(PersonService.class);
#Autowired
private transient PersonDAO personDAO;
public Person findPerson(final Long id) {
return personDAO.find(id);
}
}
If you are using Spring then use Spring Data which will do all this for you.
http://docs.spring.io/spring-data/jpa/docs/1.4.2.RELEASE/reference/html/repositories.html#repositories.core-concepts
I am running a RESTful web service on Glassfish 3.1.2 server. I use Jersey as JAX-RS implementation, Jackson as it's JSON provider, and (JPA) EclipseLink 2.5 as persistence provider for MySQL.
I'll introduce some context and then ask my question.
Let's assume we have the following hierarchy: Item entity and CraftableItem entity that inherits it (see code samples below). They both do have corresponding EAO and Resource classes: ItemEAO, CraftableItemEAO + ItemResource, CraftableItemResource (see code samples below).
Let's have two records in items table:
id | name
1 | "craftable"
2 | "non craftable"
and one corresponding record for "craftable" in crafting_items_joined:
id | crafting_time
1 | 120000
I want to get as more specific information about each entity from GET /item request as possible. I want it to return [{"id":1,"name":"craftable", "crafting_time":120000}, {"id":2,"name":"non craftable"}]. At the momment, GET /item/1 returns {"id":1,"name":"craftable", "crafting_time":120000} and GET /item/2 returns just {"id":2,"name":"non craftable"} which is the behavior i want, but for GET /item. Getting all information about entity present.
Code samples (setters are omitted for sanity's sake).
#MappedSuperclass
public abstract class BaseEntity {
protected Long id;
#Id #GeneratedValue(strategy = GenerationType.IDENTITY)
public Long getId() {
return id;
}
}
#Entity
#Inheritance(strategy = InheritanceType.JOINED)
#Table(name = "items")
public class Item extends BaseEntity implements Serializable {
private String name;
#Column(name = "name", nullable = false, unique = true)
public String getName() {
return name;
}
}
#Entity
#DiscriminatorValue("craftable")
#Table(name = "craftable_items_joined")
public class CraftableItem extends Item {
protected long craftingTime;
#Column(name = "crafting_time", nullable = false)
public long getCraftingTime() {
return craftingTime;
}
}
EAO then:
public abstract class AbstractEAO<T> {
private Class<T> entityClass;
public AbstractEAO(Class<T> entityClass) {
this.entityClass = entityClass;
}
public Class<T> getEntityClass() {
return entityClass;
}
protected abstract EntityManager getEntityManager();
// create, edit, remove
public T find(Object id) {
return getEntityManager().find(entityClass, id);
}
public List<T> findAll() {
CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
return getEntityManager().createQuery(cq).getResultList();
}
}
#Stateless
#LocalBean
public class ItemEAO extends AbstractEAO<Item> {
#PersistenceContext(unitName = "primary")
private EntityManager entityManager;
public ItemEAO() {
super(Item.class);
}
#Override
protected EntityManager getEntityManager() {
return entityManager;
}
}
#Stateless
#LocalBean
public class CraftableItemEAO extends AbstractEAO<CraftableItem> {
#PersistenceContext(unitName = "primary")
private EntityManager entityManager;
public CraftableItemEAO() {
super(CraftableItem.class);
}
#Override
protected EntityManager getEntityManager() {
return entityManager;
}
}
Resource finally:
public abstract class AbstractResource<T extends BaseEntity> {
protected abstract AbstractEAO<T> getEAO();
#GET
public List<T> findAll() {
return getEAO().findAll();
}
#GET
#Path("{id}")
public T find(#PathParam("id") Long id) {
return getEAO().find(id);
}
// create, edit, remove
}
#Stateless
#Path("item")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public class ItemResource extends AbstractResource<Item> {
#EJB private ItemEAO itemEAO;
#Override
protected AbstractEAO<Item> getEAO() {
return itemEAO;
}
}
#Stateless
#Path("item/craftable")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public class CraftableItemResource extends AbstractResource<CraftableItem> {
#EJB private CraftableItemEAO craftableItemEAO;
#Override
protected AbstractEAO<CraftableItem> getEAO() {
return craftableItemEAO;
}
}