I want to have a simple generic Entity interface pretty much like a map such as on client side in a Gwt + GwtQuery project .
public interface Entity extends JsonBuilder {
public String JsonObject getProperty(String property) ;
public Entity setProperty(String name , JsonObject obj ) ;
public String getPropertyType(String property) /* returns the actual
}
I want to be able to convert any pojo on server side to a Map form along with some type info and retrieve it on client as an Entity. Entities can be nested.
Is this doable ?
If yes. Please give some detailed guidelines.
To clarify further my goal is to have a single generic Entity interface that is capable of representing varied/diverse types of pojos from server. The type information of such a dynamic entity is expected to be available on the client side as a separate entity.
Do you think the code below will work and serve my purpose ? If yes - how will the json text underneath look like ?
public interface Tuple extends JsonBuilder {
public JsonValue get(String name);
public void set(String name, JsonValue ser);
}
public interface Entity extends Tuple {
public String getType();
public Tuple[] getTuples();
}
Related
Is there a way to implement JPA Entity using Map? either extended HashMap or contain a hashmap i.e.:
#Entity
#Table(employee)
public class Employee {
/* .... */
void set(String columnName, Object columnValue) { /*...*/ }
Object get(String columnName) { /*...*/ }
}
and
#RepositoryRestResource
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
}
this way, there is no need to provide model attributes in the Employee class. Basically, whatever columns are defined in the database, it will be a property like entry in the Employee class.
Employee emp;
...
emp.get("name");
emp.get("id");
Is something like this possible?
Though not possible in vanilla JPA, EclipseLink dynamic entities (https://wiki.eclipse.org/EclipseLink/Examples/JPA/Dynamic) might be what you want. It allows for working with entities in a map-like fashion. Not sure if it is sufficient for your use case, though.
I am looking to build a REST interface with a generic finder. The idea is to provide a search form where users can get all records by not providing any parameter or refine their search results by typing any combination of the fields.
The simple example I have annotates the JpaRepository with #RestResource which provides a nice out of the box way to add finders either by using #Query or by method name conventions
#RestResource(path = "users", rel = "users")
public interface UserRepository extends JpaRepository<User, Long>{
public Page<User> findByFirstNameStartingWithIgnoreCase(#Param("first") String fName, Pageable page);
}
I am looking to add a custom finder that would map my parameters and would leverage the paging, sorting and REST support where the actual implementation query will be composed dynamically (probably using QueryDSL) the method will have n parameters (p 1 ... p n) and will look like:
public Page<User> findCustom(#Param("p1") String p1, #Param("p2") String p2, ... #Param("pn") String pn, Pageable page);
I have tried the approach described in:
http://docs.spring.io/spring-data/data-jpa/docs/current/reference/html/repositories.html#repositories.custom-implementations
but my custom method is not available from the repository's REST interface (/users/search)
I hope someone already figured this out and would be kind to give me some direction.
Try something like this but of course adopted to your scenario:
public interface LocationRepository extends CrudRepository,
PagingAndSortingRepository,
LocationRepositoryExt {
}
public interface LocationRepositoryExt {
#Query
public List findByStateCodeAndLocationNumber(#Param("stateCode") StateCode stateCode, #Param("locationNumber") String locationNumber);
}
class LocationRepositoryImpl extends QueryDslRepositorySupport implements LocationRepositoryExt {
private static final QLocation location = QLocation.location;
public LocationRepositoryImpl() {
super(Location.class);
}
#Override
public Page findByStateAndLocationNumber(#Param("state") State state, #Param("locationNumber") String locationNumber, Pageable pageable) {
List locations = from(location)
.where(location.state.eq(state)
.and(location.locationNumber.eq(locationNumber)))
.list(location);
return new PageImpl(locations, pageable, locations.size());
}
}
I am not able to serialize nested entities.
This is my transfer object
[ProtoContract]
[Serializable]
[DataContract]
public class MyClassTO
{
[ProtoMember(1)]
[DataMember]
public List<MyEntity> ListOfMyEntities {get;set;};
}
On my backend, I fire the following linq to entities query, fill the transfer object and return it to the client:
var myClassTO = new MyClassTO();
myClassTO.ListOfMyEntities = Context.MyEntity.Include("ReferencedEntity.AnotherReferencedEntity").ToList;
return myClassTO;
The client receives the list of MyEntity objects but included entities are not serialized(they are all null). Does anybody have any idea about it?
I have the following code:
public interface IKeyed<TKey>
{
TKey Id { get; }
}
// This is the entity framework generated model. I have added the
// IKeyed<Guid> interface
public partial class Person : IKeyed<Guid>
{
public Guid Id { get; set; }
}
public class Repository<TKey, TEntity> : IKeyedRepository<TKey, TEntity>
where TEntity : class, IKeyed<TKey>
{
private readonly IObjectSet<TEntity> _objectSet;
public Repository(IOjectSet<TEntity> objectSet)
{
_objectSet = objectSet;
}
public TEntity FindBy(TKey id)
{
return _objectSet.FirstOrDefault(x => x.Id.Equals(id));
}
}
[Update]
Here is how I am calling this:
Db2Entities context = new Db2Entities(_connectionString); // This is the EF context
IObjectSet<Person> objectSet = context.CreateObjectSet<Person>();
IKeyedRepository<Guid, Person> repo = new Repository<Guid, Person>(objectSet);
Guid id = Guid.NewGuid();
Person person = repo.FindBy(id); // This throws the exception.
The above code compiles. When the 'FindBy' method is executed, I get the following error:
Unable to create a constant value of type 'Closure type'. Only primitive types (for instance Int32, String and Guid) are supported in this context.
Since the type of my 'Id' is a Guid (one of the primitive types supported) it seems like I should be able to massage this into working.
Anyone know if this is possible?
Thanks,
Bob
It doesn't work this way. You cannot call Equals because EF doesn't know how to translate it to SQL. When you pass expression to FirstOrDefault it must be always only code which can be translated to SQL. It is probably possible to solve your problem with some manual building of expression tree but I can reference other solutions already discussed on Stack Overflow.
ObjectContext offers method named GetObjectByKey which is exactly what you are trying to do. The problem is that it requires EntityKey as parameter. Here are two answers which show how to use this method and how to get EntityKey:
Entity Framework Simple Generic GetByID but has differents PK Name
generic GetById for complex PK
In your case the code will be less complicated because you know the name of the key property so you generally need only something like this:
public virtual TEntity FindBy(TKey id)
{
// Build entity key
var entityKey = new EntityKey(_entitySetName, "Id", key);
// Query first current state manager and if entity is not found query database!!!
return (TEntity)Context.GetObjectByKey(entityKey);
}
The problem here is that you cannot get entitySetName from IObjectSet so you must either pass it to repository constructor or you must pass ObjectSet.
Just in case you will want to use DbContext API (EFv4.1) in the future instead of ObjectContext API it will be much simplified because DbSet offers Find method:
generic repository EF4 CTP5 getById
Can RequestFactory handle composite primary keys?
The documentation mentions that entities must implement getId(); how should this be implemented in the case where entities do not have a single "id" field, but rather have multiple foreign key fields that together constitute a composite primary key?
In GWT 2.1.1, the Id and Version properties may be of any type that RequestFactory knows how to transport. Basically, any primitive type (int), boxed type (Integer), or any object that has an associated Proxy type. You don't have to reduce a composite id to a String yourself; the RF plumbing can take care of composite keys automatically by using the persistent id of an entity-type key or the serialized state of a value-type key.
Using the previously-posted example:
interface Location {
public String getDepartment();
public String getDesk();
}
interface Employee {
public Location getId();
public int getVersion();
}
#ProxyFor(Location.class)
interface LocationProxy extends ValueProxy {
// ValueProxy means no requirement for getId() / getVersion()
String getDepartment();
String getDesk();
}
#ProxyFor(Employee.class)
interface EmployeeProxy extends EntityProxy {
// Use a composite type as an id key
LocationProxy getId();
// Version could also be a complex type
int getVersion();
}
If you can't reduce the identity to a single getId() property on the domain type, you can use a Locator to provide an externally-defined id and version property. For example:
#ProxyFor(value = Employee.class, locator = EmployeeLocator.class)
interface EmployeeProxy {.....}
class EmployeeLocator extends Locator<Employee, String> {
// There are several other methods to implement, too
String getId(Employee domainObject) { return domainObject.getDepartment() + " " + domainObject.getDesk(); }
}
The DevGuide linked from the question is a bit out of date with respect to
RequestFactory changes in 2.1.1