I'm trying to map a model of a webservice where every List is inside nested object to something more simple.
Model 1
public class Parent {
private Children children;
}
public class Children {
private List<Child> children;
}
public class Child {
}
Model 2(simplified)
public class Parent2 {
private List<Child2> children;
}
public class Child {
}
The mapping is pretty straightforward:
#Mappings({#Mapping(source = "entity.children.children", target = "children")})
Parent2 parentToParent2(Parent entity);
#InheritInverseConfiguration
Parent parent2ToParent(Parent2 entity);
Mapping works fine except for one problem. When I map Parent with null children to Parent2 and back to Parent, the Children object is created with empty list. Is there some way to prevent that?
You can achieve that with both a mapper decorator or an AfterMapping hook.
Decorator
Decorator:
public abstract class MapperDecorator implements Mapper {
private final Mapper delegate;
public MapperDecorator(Mapper delegate) {
this.delegate = delegate;
}
#Override
public Parent parent2ToParent(Parent2 entity) {
Parent parent = delegate.parent2ToParent(entity);
if (entity.getChildren() == null) {
parent.setChildren(null);
}
return parent;
}
}
Mapper:
#org.mapstruct.Mapper
#DecoratedWith(MapperDecorator.class)
public interface Mapper {
#Mapping(source = "entity.children.children", target = "children")
Parent2 parentToParent2(Parent entity);
#InheritInverseConfiguration
Parent parent2ToParent(Parent2 entity);
Child2 childToChild2(Child entity);
Child child2ToChild(Child2 entity);
}
AfterMapping
Mapper:
#org.mapstruct.Mapper
public abstract class Mapper {
#Mapping(source = "entity.children.children", target = "children")
public abstract Parent2 parentToParent2(Parent entity);
#InheritInverseConfiguration
public abstract Parent parent2ToParent(Parent2 entity);
public abstract Child2 childToChild2(Child entity);
public abstract Child child2ToChild(Child2 entity);
#AfterMapping
public void afterParent2ToParent(Parent2 source,
#MappingTarget Parent target) {
if (source.getChildren() == null) {
target.setChildren(null);
}
}
}
Related
I want to reuse my AbstractDAO in a new project, except this time I don't want to use EJB annotations - just CDI ones.
So far, I've been using it like this:
public abstract class AbstractDAO<T> {
#PersistenceContext(unitName = "myUnit")
private EntityManager entityManager;
private Class<T> entityClass;
public AbstractDAO(Class<T> entityClass) {
this.entityClass = entityClass;
}
protected EntityManager getEntityManager() {
return entityManager;
}
public void save(T entity) {
entityManager.persist(entity);
}
public void update(T entity) {
entityManager.merge(entity);
}
public void remove(T entity) {
entityManager.remove(entityManager.merge(entity));
}
public T findById(Object id) {
return entityManager.find(entityClass, id);
}
public List<T> findBy(String attrName, Object attrValue) {
// Impl here
}
// [...] Many more search methods
}
And I've been creating a DAO for each Entity, like this for example:
#Stateless
public class UserDAO extends AbstractDAO<User> {
public UserDAO() {
super(User.class);
}
public User findByUsername(String username) {
if (username != null) {
return super.findOneBy("username", username.toLowerCase());
}
return null;
}
}
Now I would like to get rid of the #Stateless annotation. But simply replacing it with a #RequestScoped one won't work because of the non-private constructor with no parameters requirement of JSR-346
How can I refactor my DAO to a pure CDI one ?
Two issues here: CDI beans are not transaction aware by default -unlike EJBs, so you will have to use #Transactional qualifier if you want to do saves/updates...
Second, your no-arg constructor: you only need to pass the entity class to your abstract class even though you also specify it as a generic argument. You can infer the actual class like this:
public class AbstractDAO<T> {
private transient Class<T> entityClass;
#SuppressWarnings("unchecked")
public AbstractDAO() {
Type generSuperCls = getClass().getGenericSuperclass();
if (generSuperCls instanceof Class) {
generSuperCls = ((Class<?>) generSuperCls).getGenericSuperclass();
}
ParameterizedType parameterizedType = (ParameterizedType) generSuperCls;
Type type = parameterizedType.getActualTypeArguments()[0];
if (type instanceof Class) {
this.entityClass = (Class<T>) type;
} else if (type instanceof ParameterizedType) {
this.entityClass = (Class<T>) ((ParameterizedType) type).getRawType();
}
}
#PersistenceContext
private EntityManager em;
public T getById(Object id) throws ServiceException {
return getEm().find(entityClass, id);
}
// other methods follow
}
As a side note, why do you want to get rid of EJBs? Benchmarks show you get better performance using pooled slsb than cdi and they together very well(every EJB beans is also a CDI bean in jee container).
Is there a way to pass the enclosed object reference as a parameter to the mapping method?
public class Car {
public int id;
public Person driver;
}
public class Person {
public int carId;
}
I need a reference to the enclosing car object when mapping the person object in the personToPersonDtoAfterMapping custom method.
#Mapper
public abstract class CarMapper {
public abstract CarDto carToCarDto(Car car);
public abstract PersonDto personToPersonDto(Person person);
#AfterMapping
protected void personToPersonDtoAfterMapping(Person person, #MappingTarget PersonDto dto, Car enclosedCar) {
dto.setCarId(enclosedCar.getId())
}
}
Simply use #Context annotation. Did you try?
#Mapper
public abstract class CarMapper {
public abstract CarDto carToCarDto(Car car);
public abstract PersonDto personToPersonDto(Person person, #Context Car enclosedCar);
#AfterMapping
protected void personToPersonDtoAfterMapping(Person person, #MappingTarget PersonDto dto, #Context Car enclosedCar) {
dto.setCarId(enclosedCar.getId())
}
}
I want to create a remote EJB for an entity class. Is there a way of implementing a method with one parameter beign an object of a class that specifically has the #Entity annotation? The purpose of this, is to create just one bean for all my entities.
Example:
public void save(Entity ent){
em.persist(ent);
}
If you just have 1 ejb for all entities you will soon run into problems when you have to handle some of them in a special way.
But you can do like this with an abstract super-ejb, and still have 1 ejb per entity, but its very easy to create. And you can still overwrite the default, inherited methods.
public abstract class AbstractEjb<T> {
private Class<T> entityClass;
public AbstractEjb(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);
}
public List<T> findAll() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
return getEntityManager().createQuery(cq).getResultList();
}
public List<T> findRange(int[] range) {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
javax.persistence.Query q = getEntityManager().createQuery(cq);
q.setMaxResults(range[1] - range[0] + 1);
q.setFirstResult(range[0]);
return q.getResultList();
}
public int count() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
javax.persistence.criteria.Root<T> rt = cq.from(entityClass);
cq.select(getEntityManager().getCriteriaBuilder().count(rt));
javax.persistence.Query q = getEntityManager().createQuery(cq);
return ((Long) q.getSingleResult()).intValue();
}
}
To implement for an entity just do
#Stateless
public class TestEjb extends AbstractEjb<TestEntity> {
#PersistenceContext(unitName = "...")
private EntityManager em;
public TestEjb() {
super(TestEntity.class);
}
public EntityManager getEntityManager() {
return em;
}
}
Source: Generate JSF pages from entity classes in Netbeans.
Using a combination provided from this example and this implementation I am trying to create a solution that decouples the UnitOfWork class from the individual repositories, as they violate the Open-Closed Principle, since every time you added a new repository you would have to modify the UnitOfWork class. I am using Unity as the IoC container to wire up dependencies.
The problem I have is that in automatically wiring up the UnitOfWork, IDbContext and the repositories (IEmployeeRepository and ICustomerRepository) using Unity, the repositories will be injected with separate instances of the UnitOfWork, which, of course, defeats the purpose. I need to share the context across the repositories, and it seems I am missing a piece to this puzzle - at the moment (see Service layer) the UnitOfWork instantiated will be different to the UnitOfWork for each of repositories.
How do inject the IUnitOfWork into the service layer and pass this instantiated shared UnitOfWork class to the respective repositories, using Unity and dependency injection?
Here's my proposed (fabricated) solution:
Repositories
public interface IRepository<TEntity> where TEntity : class
{
TEntity Create();
// omitted for brevity
}
public class Repository<TEntity> : IRepository<TEntity>
where TEntity : class
{
private readonly DbContext _context;
public Repository(IUnitOfWork uow)
{
_context = uow.Context;
}
public virtual TEntity Create(TEntity entity)
{
return _context.Set<TEntity>().Add(entity);
}
// omitted for brevity
}
public interface IEmployeeRepository : IRepository<Employee>
{
}
public interface ICustomerRepository : IRepository<Customer>
{
}
public class EmployeeRepository : Repository<Employee>
{
public EmployeeRepository(IUnitOfWork uow)
: base(uow)
{
}
}
public class CustomerRepository : Repository<Customer>
{
public CustomerRepository(IUnitOfWork uow)
: base(uow)
{
}
}
DbContext Factory
public interface IDbContextFactory
{
DbContext GetContext();
}
public class DbContextFactory : IDbContextFactory
{
private readonly DbContext _context;
public DbContextFactory()
{
_context = new MyDbContext("ConnectionStringName");
}
public DbContext GetContext()
{
return _context;
}
}
Unit Of Work
public interface IUnitOfWork
{
void SaveChanges();
DbContext Context { get; }
}
public class UnitOfWork : IUnitOfWork, IDisposable
{
private readonly DbContext _context;
private bool disposed = false;
public UnitOfWork(IDbContextFactory contextFactory)
{
_context = contextFactory.GetContext();
}
public void SaveChanges()
{
if (_context != null)
{
_context.SaveChanges();
}
}
public DbContext Context
{
get { return _context; }
}
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
_context.Dispose();
}
}
disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
Service
public class CompanyService
{
private readonly IUnitOfWork _uow;
private readonly IEmployeeRepository _employeeRepository;
private readonly ICustomerRepository _customerRepository;
public CompanyService(IUnitOfWork uow, IEmployeeRepository employeeRepository, ICustomerRepository customerRepository)
{
_uow = uow;
_employeeRepository = employeeRepository;
_customerRepository = customerRepository;
}
// over-simplified example method
public void AddEmployeeAndCustomer()
{
_employeeRepository.Create(new Employee {Id = 1, Name = "Test Employee"});
_customerRepository.Create(new Customer { Id = 2, Name = "Test Customer" });
_uow.SaveChanges();
}
}
I think what you are looking for is a per request lifetime manager so that you only get one UnitOfWork instance and one DbContext instance for the duration of a request. Unity 3 has the Unity bootstrapper for ASP.NET MVC which has a PerRequestLifetimeManager which lets you do this.
If you are not using ASP.NET then you could probably use a PerResolveLifetimeManager. Another approach I've seen is a HierarchicalLifetimeManager combined with a child container (which makes the registrations a singleton within the child container).
I am trying to work with generic repositories in entity framework and came across this code below:
public class GenericRepository<TContext, TEntity> : IGenericRepository<TEntity>
where TContext : IUnitOfWork
where TEntity : class
{
protected TContext _context;
/// <summary>
/// Constructor that takes a context
/// </summary>
/// <param name="context">An established data context</param>
public GenericRepository(TContext context)
{
_context = context;
}
public IQueryable<TEntity> Select()
{
return _context.Set<TEntity>().AsQueryable();
}
public IEnumerable<TEntity> GetAll()
{
return _context.Set<TEntity>().AsEnumerable();
}
public IEnumerable<TEntity> Where(Func<TEntity, bool> predicate)
{
return _context.Set<TEntity>().Where(predicate);
}
public TEntity GetSingle(Func<TEntity, bool> predicate)
{
return _context.Set<TEntity>().Single(predicate);
}
public TEntity GetFirst(Func<TEntity, bool> predicate)
{
return _context.Set<TEntity>().First(predicate);
}
public void Add(TEntity entity)
{
if (entity == null)
throw new ArgumentException("Cannot add a null entity");
_context.Set<TEntity>().Add(entity);
}
public void Delete(TEntity entity)
{
if (entity == null)
throw new ArgumentException("Cannot delete a null entity");
_context.Set<TEntity>().Remove(entity);
}
public void Attach(TEntity entity)
{
if (entity == null)
throw new ArgumentException("Cannot attach a null entity");
_context.Set<TEntity>().Attach(entity);
}
#region IDisposable implementation
private bool disposedValue;
public void Dispose(bool disposing)
{
if (!this.disposedValue)
{
if (disposing)
{
// dispose managed state here if required
}
// dispose unmanaged objects and set large fields to null
}
this.disposedValue = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
However I find it a little difficult to understand the need for the constructor created
/// <summary>
/// Constructor that takes a context
/// </summary>
/// <param name="context">An established data context</param>
public GenericRepository(TContext context)
{
_context = context;
}
Can someone please explain the use of this?
Thanks
That's because there may be multiple DbContext class in your project, So you need to inject a specific DbContext instance to tell the GenericRepository class which DbContext you are using.
The reason you need to have multiple DbContext class maybe are:
Your project target to several Databases;
Your project is large, for the consideration of performance and maintainability, you want to split it into several modules. For Example:
public class BaseContext<TContext> : DbContext
where TContext : DbContext, new()
{
protected BaseContext()
: base("name=ConnectionString")
{
}
}
public class ShopDbContext :BaseContext<ShopDbContext>
{
public DbSet<Product> Products{ get; set; }
}
public class BlogDbContext :BaseContext<BlogDbContext>
{
public DbSet<Blog> Blogs{ get; set; }
}
Now, if you want to query the Products, you must instantiate the ShopDbContext, and pass it into the GenericRepository constructor(IoC is a good choice).