At this moment I start work on small web application based on MVC.
Now I try implement main classes for Model layout using DAO pattern.
So, first of all I create two entity classes (for example): Author and Book:
package myProject.model.entity;
import java.io.Serializable;
public class Author implements Serializable {
private static final long serialVersionUID = 7177014660621405534L;
private long id;
private String firstName;
private String lastName;
public Author() {
}
// getter and setter methods here
}
and Book class:
package myProject.model.entity;
import java.io.Serializable;
public class Book implements Serializable {
private static final long serialVersionUID = 7177014660621405534L;
private long id;
private String title;
private String description;
public Book() {
}
// getter and setter methods here
}
On next step, I see, that classes Book and Author both have getId() and setId().
so, I create interface Persistent for my Entity classes:
package myProject.model.entity;
public interface Persistent {
public long getId();
public void setId(long id);
}
So, first my question:
It is correct implementation for model package?
On the next step, I start implement classes for package dao.
package myProject.model.dao;
import java.util.List;
import myProject.model.entity.Persistent;
public interface Dao {
Persistent get(long id);
void save(Persistent persistent);
void delete(long id);
}
Next step: create interfaces AuthorDao and BookDao, that extend base dao interface Dao
But both interfaces: AuthorDao and BookDao - at this moment empty.
What do you think - it in normal, that interfaces empty? It is my second question.
And on the last step I create package model.dao.hibernate and add to the package to class AuthorDaoHibernate and BookDaoHibernate - both class implements AuthorDao and BookDao interfaces.
And My main question now:
my interface Dao work with objects type Persistent and I dont use Generics. And all ok and nice.
What do you thinks - what benefits I have, if I re-work Dao interface wit Generics:
package myProject.model.dao;
import java.util.List;
import myProject.model.entity.Persistent;
public interface Dao<Persistent> {
T get(long id);
List<T> getAll();
void save(T persistent);
void delete(long id);
}
My Dao classes work only with persistent entities - no any other object type...
Do you really any reasons in me case use Generics?
Generics can greatly improve code readability and reduce errors that could come from wrong casting.
We're using something similar to what you described (note that there are interfaces and implementations needed).
Here's a basic example (I'll leave the getters and setters out for brevitiy):
#MappedSuperClass
class BaseEntity {
#Id
private int id;
}
#Entity
class UserEnity extends BaseEntity {
//user stuff like name
}
class BaseDAO<T extends BaseEntity> {
public T findById(int id) {
...
}
//other generic CRUD methods
}
#Stateless
class UserDAO extends BaseDAO<UserEntity> {
//additional user specific methods
}
Using UserDAO would then be like this:
UserDAO userDao; //some injection or lookup
//no explicit cast needed here, thanks to generics
UserEntity user = userDao.findById(userId);
//compiler error due to the generic parameter being UserEntity and AnotherEntity doesn't extend that
AnotherEntity a = userDao.findById(someId);
If you want to use generics you should define Dao as following:
public interface Dao<T extends Persistent> {
.....................
void save(T persistent);
...................
}
Now when you extend it you will have to create save that accepts Book only:
public class Book extends Dao<Book> {
.....................
void save(Book persistent);
...................
}
The benefit here is that you cannot pass Author to BookDao. This will not pass compilation.
BTW if you are using Hibernate, JPA or other ORM solution you do not really have to create DAO per entity. One generic dao can solve all your needs.
There is no reason here. If it's unique, it's not generic, by definition !
List getAll() will do the Job.
The ArrayList is Generic because it will sometimes return Persistent, sometime President.
Related
I have the following class structure (it actually is a VO layer with Hibernate mappings):
public abstract class abstractClassVO {
private int id;
private String name;
}
public class concreteClassAVO extends abstractClassVO {
private String aAttribute;
}
public class concreteClassBVO extends abstractClassVO {
private Long bAttribute;
}
And the equivalent DTO objects:
public abstract class abstractClassDTO {
private int id;
private String name;
}
public class concreteClassADTO extends abstractClassDTO {
private String aAttribute;
}
public class concreteClassBDTO extends abstractClassDTO {
private Long bAttribute;
}
Then I have another object like this:
public class compositeObject {
private int anAttribute;
private abstractClassVO myInstance;
}
and its equivalent:
public class compositeObjectDTO{
private int anAttribute;
private abstractClassDTO myInstance;
}
How can I tell dozer to automatically map myInstance to the specific DTO that corresponds to the concrete class implementation in the VO layer?
Currently, out of the box, Dozer isn't even putting anything in the myInstance field of the compositeObjectDTO class. My guess is that it's due to the fact that abstractClassDTO it is an abstact class, and since it cannot determine the implementation, it does nothing. I am not getting any exceptions.
Dozer can't do it out of the box but you could write a helper that would determine destination class by source class. You can get this information from DozerBeanMapper.getMappingMetadata().getClassMappings* methods. These methods return list of ClassMappingMetadata that contains destination class. You just only need to chech whether destination class is inherited from abstractClassDTO. This check can be omitted if you only have one mapping for one VO.
For bi-directional mapping you should additionally check ClassMappingMetadata.MappingDirection field.
I'm using neo4j + spring data. To access the data I'm using interfaces, that extends GraphRepository<E>. For example
public interface EntryRepository extends GraphRepository<Entry> {
#Query("start parent=node({0}), entry=node({1}) "
+ "match parent-[*1..2{removed:false}]->entry "
+ "return distinct entry")
Entry findOne(Long parentId, Long entryId);
}
I'm trying to get data, that differs from my domain models. My custom models looks like that
#QueryResult
public class EntryBean {
#ResultColumn("id")
private Long id;
#ResultColumn("name")
private String name;
#ResultColumn("content")
private String content;
...
//getters and setters
}
#QueryResult
public class BoardBean {
#ResultColumn("id")
private Long id;
#ResultColumn("name")
private String name;
...
//getters and setters
}
Obviously, that it will be better to separate duplicate fields to Base class and inherit from it. So, i'm doing next steps
#QueryResult
public class BaseBean {
#ResultColumn("id")
private Long id;
#ResultColumn("name")
private String name;
...
}
#QueryResult
public class EntryBean extends BaseBean{
#ResultColumn("content")
private String content;
...
//getters and setters
}
And I don't need BoardBean anymore. But when I'm trying run query
public interface EntryRepository extends GraphRepository<Entry> {
#Query("start user=node({0}), board=node({1}) "
+ "... "
+ "return id(entry) as id, entry.name as name, entry.content as content")
List<EntryBean> getRelatedEntries(Long userId, Long boardId);
}
I get filled by data just fields that directly declared into EntryBean class (i. e. "content" field).
So, How I can correctly implement the #QueryResult class hierarcy?
This is a bug which has been present for almost two years (even in 2.3.5.RELEASE!) in the class in charge of converting annotated POJOs.
Indeed, it calls getDeclaredFields on the most concrete type thus skipping possibly inherited annotated fields.
Before the issue is fixed, my piece of advice would be to tolerate this superficial field duplication on your side and not relying on inheritance for now.
i've a base class that provide only identification:
public abstract class Identifable<T> {
#Id
private T id = null;
public T getId() {
return id;
}
public void setId(T id) {
this.id = id;
}
public boolean hasId() {
return id != null;
}
}
and several subclasses that extends it like:
#Entity
#Cache
public class MyEntity extends Identifable<String> {
/* some specific attributes and methods */
}
I get an java.lang.IllegalStateException: #Id field 'id' in com.mypkg.MyEntity must be of type Long, long, or String.
Why? Can't Objectify see the inherited #Id field?
Thanks
The cause:
Objectify only inspects types at runtime using reflection. Because of type erasure all unbounded type parameters are during compilation converted to Object type, which is what objectify sees and complains.
The solution:
Use concrete type for id field. Possibly move it to a child class, as proposed by #Anthony.
In JPA, you must use for a field marked with #Id one of the following types:
any Java primitive type; any primitive wrapper type; java.lang.String; java.util.Date; java.sql.Date; java.math.BigDecimal; java.math.BigInteger
Just remove the generics from the base class and use one of the mentioned types for your id field.
Let's reason about if for a while... You are trying to build a super type in which the type of the ID varies. Are you sure that this is what you want objectify to build (a hierarchy of objects in which the root entity has a unknown ID type)? While I've seen this kind of code in several ORM frameworks, this is how I would build what you want.
Interface (not part of the object hierarchy):
public interface Identifable<T> {
public T getId();
public void setId(T id);
public boolean hasId();
}
Root of your hiearchy implements Identifable with a concrete type for the id:
#Entity
public class MyBaseClass implements Identifable<String> {
#Id
private String id = null;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public boolean hasId() {
return id != null;
}
}
And subclass comes naturally out of it:
#EntitySubclass(index=true)
public class MyEntity extends MyBaseClass {
// fields, accessors and mutators
}
currently I'm trying to implement a typed generic DAO.
I do not even get to compile anything, since NetBeans complains about UserDAOHibernate
interface expected here
type argument User is not within bounds of type-variable ENTITY
I'm afraid there is some obvious mistake in how I use inheritance/interfaces, since I'm rather new to Java.
Here's some stripped down code
public interface GenericEntity<ID extends Serializable> {
public abstract ID getId();
public abstract void setId(final ID id);
}
public abstract class LongEntity implements GenericEntity<Long> {
protected Long id;
public Long getId();
public void setId(final Long id);
}
public class User extends LongEntity implements Serializable {
private String name;
private String password;
private Customer customer;
}
public interface GenericDAO<ENTITY extends GenericEntity<ID>, ID extends Serializable> {
public abstract ENTITY findById(ID id);
public abstract List<ENTITY> findAll();
public abstract ENTITY makePersistent(ENTITY entity);
public abstract void makeTransient(ENTITY entity);
}
public abstract class GenericHibernateDAO<ENTITY extends GenericEntity<ID>, ID extends Serializable>
implements GenericDAO<ENTITY, ID> {
}
public class UserDAOHibernate implements GenericHibernateDAO<User, LongEntity> {
}
Is it that LongEntity should extend GenericEntity<Long>? If so, how would I do this with Java's single level or inheritance?
Is this layered approach a bad example to follow? All my entities need an id and this implementation could easily be reused lateron with different id types, so I thought I might use it.
The error comes from here:
public class UserDAOHibernate implements GenericHibernateDAO<User, LongEntity> {
}
You've specified that GenericHibernateDAO's ID parameterized type is bounded by <ID extends Serializable>.
LongEntity extends GenericEntity, and hence, why you have a type mismatch.
Also, GenericHibernateDAO is an abstract class (and not an interface), so you'll need to extends instead of implements.
The correct solution should be:
public class UserDAOHibernate extends GenericHibernateDAO<User, Long> {
}
Given a generic tree based (Java) data model. Let's say
abstract class XModel {
long id;
XModel parent;
}
class ProjectModel extends XModel {
String customer;
}
class FileModel extends XModel {
String name;
}
class FolderModel extends XModel {
String name;
String attributes;
}
My challenge is to make sure that FileModels are only used in FolderModels (or PrjectModels) and FolderModels are only used in ProjectModels.
Since the model should be extensible - is there any generic way to do this constraint validation (like XML Schema does) without hardcoding the parent-child-realtions in a validation method?
I'm not sure how useful it would be - depends on how you create the tree, but this might work:
abstract class XModel<T extends XModel> {
long id;
T parent;
}
class ProjectModel extends XModel { ... }
class FolderModel extends XModel<ProjectModel> { ... }
class FileModel extends XModel<FolderModel> { ... }
UPDATE
To separate validation logic from model itself you could use some runtime validators like Hibernate or Spring validators.
I would use generics and interfaces that describe the restrictions
interface Model {
}
abstract class AbstractModel<P extends Model> implements Model {
Long id;
P parent;
}
class ProjectModel extends AbstractModel implements HasFileModel,
HasFolderModel {
}
interface HasFileModel extends Model {
}
static class FileModel extends AbstractModel<HasFileModel> {
}
interface HasFolderModel extends Model {
}
class FolderModel extends AbstractModel<HasFolderModel> implements
HasFileModel {
}
This way the child only restricts the parent to an interface not a concrete type
If you don't want to put those constraints into code, you'd have to write a validation method that is fed by some external data yourself. AFAIK there's no such built in option (in the compiler) besides using Generics, which would require you to express the constraints in code.