Can I define an object to a model with Play framework? - orm

UserRole is an abstract class, it has three concrete classes with three different roles. However, each time I crate a new User with a new Role, the Role remains null!
Here is the code of the User:
#Entity
public class User extends Model {
#Id
public Long id;
#Constraints.Required
#Formats.NonEmpty
#Column(unique = true)
public String email;
#Constraints.Required
#Formats.NonEmpty
#Column(unique = true)
public String fullname;
public String confirmationToken;
#Constraints.Required
#Formats.NonEmpty
public String passwordHash;
#Formats.DateTime(pattern = "yyyy-MM-dd HH:mm:ss")
public Date dateCreation;
#Formats.NonEmpty
public Boolean validated = false;
**public UserRole role;**
}

Related

AutoMapper assign property from parent type property

is there i way in autoMapper to assign child class property from parent class property. I have looked at other example out there but didn't quite get what I need so posting my issue here.
here's code
class ParentDB {
public int id;
public DateTime CreatedDate;
public string Name;
}
class ChildDB {
public int id;
publi string Name;
public int Number;
}
class ParentViewModel : IMapFrom <ParentDB> {
pulic int id;
pulic string Name;
public ChildViewModel child;
}
class ChildViewModel : IMapFrom <ChildDB> {
public int Id;
pulic string Name;
pulic DateTime ParentCreated;
}
public interface IMapFrom<T>
{
void Mapping(Profile profile) => profile.CreateMap(typeof(T), GetType());
}
Problem is that "ParentCreated" time in ChildViewMode needs to come from ParentDB. I have tried following with no success
class ParentViewModel : IMapFrom <ParentDB> {
pulic int id;
pulic string Name;
public ChildViewModel child;
public DateTime CreatedDate;
public void Mapping(Profile profile)
{
profile.CreateMap<ParentDB, ParentViewModel>()
.AfterMap( (s,d) => d.ChildViewModel.ParentCreated = d.CreatedDate);
}
}
var children = await Context.ParentDB
.ProjectTo<ParentViewModel>(mapper.ConfigurationProvider)
.ToListAsync()
with above although ParentViewModel.CreatedDate has date, ChildViewModel.ParentCreated is null. can some please explain why its not assigning date in AfterMap and hwo can this be fix.
Thanks
I am not how to do the map in the way you shared, since I can't see the IMapFrom <T> interface.
Maybe you can try below:
var parent = new ParentDB { id = 1, Name = "AA", CreatedDate = DateTime.Now.AddDays(1) };
var configuration = new MapperConfiguration(cfg => {
cfg.CreateMap<ParentDB, ParentViewModel>()
.AfterMap((s, d) => d.ChildViewModel.ParentCreated = s.CreatedDate);
});
var mapper = configuration.CreateMapper();
ParentViewModel parentViewModel = mapper.Map<ParentViewModel>(parent);
Also you should initlize the ChildVewModel in the ParentViewModel, otherwise it will occur a NullReference exception
public class ParentViewModel
{
public ParentViewModel()
{
ChildViewModel = new ChildViewModel();
}
public int id;
public string Name;
public ChildViewModel ChildViewModel;
}
Result:

#Indexed annotation is ignored

I have a simple Product class as it follows
#SolrDocument(collection = "product")
public class Product {
#Id
#Indexed(name = "id", type = "string")
private String id;
#Field
#Indexed(name = "namex", type = "text_general", stored = false, searchable=true)
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
my problem is that the annotation #Indexed is completely ignored. The name of the field is simply name (instead of namex) and the field is stored. Any guess?
UPDATE 1 if I remove the type annotation name works, but stored has no effect still
I managed by modifying the bean that creates the SolrTemplate object like follows:
#Bean
public SolrTemplate solrTemplate(SolrClient client) throws Exception {
SolrTemplate st = new SolrTemplate(client);
st.setSchemaCreationFeatures(Collections.singletonList(Feature.CREATE_MISSING_FIELDS));
st.afterPropertiesSet();
return st;
}

#Query Spring Data JPA Update Not Working

Here is my User entity:
#Entity
#Table(name="users")
public class User implements IBaseEntity<User> {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long userId;
#Column(unique = true)
#NotNull
private String username;
#Column(unique = true)
#NotNull
private String email;
#Column
#NotNull
private String password;
// #formatter:off
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "users_roles",
joinColumns = { #JoinColumn(name = "user_id") },
inverseJoinColumns = { #JoinColumn(name = "role_id") })
// #formatter:on
private List<Role> roles = new ArrayList<Role>();
#Column
#NotNull
private Boolean locked;
...
}
Here is my Role entity:
#Entity
#Table(name="roles")
public class Role implements IBaseEntity<Role> {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long roleId;
#Column(unique = true)
#NotNull
private String name;
...
}
Here is my User service:
package org.quickloanconnect.service;
public interface IUsersService extends IBaseService<User>{
public void updateUserRolesById(List<Role> roles, Long userId);
...
}
Here is the UserServiceImpl :
#Service
#Transactional
public class UsersServiceImpl extends AbstractServiceImpl<User> implements
IUsersService {
...
#Override
#Transactional
public void updateUserRolesById(List<Role> roles, Long user_id) {
userDao.updateUserRolesById(roles, user_id);
}
...
}
And here is the dao:
public interface IUsersDao {
...
#Modifying
#Query("UPDATE User u SET u.roles = :roles WHERE u.userId = :userId")
public void updateUserRolesById(#Param("roles") List<Role> roles,
#Param("userId") Long userId);
...
}
When I run this update, I get the following: SqlExceptionHelper : No value specified for parameter 2 . What is causing this? When I update my user with a single role, I see that a List of size one is getting to the dao with the correct userId (both parameters present), but the update seems to fail at the dao level with the "SqlExceptionHelper : No value specified for parameter 2" error message.

JPA #ManyToOne fields are empty

I have spent hours looking how to solve this. When I try to get parent from a child all but it's id fields are empty. It just makes no sense. I am using PlayFramework 2.0.4 if that might indicate anything (besides a terrible choice of framework).
TRoute.java (parent)
#Entity
#Table(name="routes")
public class TRoute extends Model {
#Id
public String route_id;
public String agency_id;
#Constraints.Required
public String route_short_name;
#Constraints.Required
public String route_long_name;
public String route_desc;
#Constraints.Required
public String route_type;
public String route_url;
public String route_color;
public String route_text_color;
#OneToMany(mappedBy="troute")
public List<Trip> trips;
public static Finder<String, TRoute> find = new Finder(
String.class, TRoute.class
);
}
Trip.java (child)
#Entity
#Table(name="trips")
public class Trip extends Model {
#Constraints.Required
public String route_id;
#Constraints.Required
public String service_id;
#Id
public String trip_id;
public String trip_headsign;
public String direction_id;
public String block_id;
public String shape_id;
#ManyToOne
#JoinColumn(name="route_id")
public TRoute troute;
public static List<Trip> byRouteId(String route_id) {
List<Trip> trips =
Trip.find
.where().like("route_id", route_id)
.findList();
return trips;
}
public static Finder<String, Trip> find = new Finder(
String.class, Trip.class
);
}
The finder has a fetch() method which can be used to load properties of the other table. Something like:
public static List<Trip> byRouteId(String route_id) {
List<Trip> trips = List<Trip> trips = Trip.find
.fetch("troute") // fetch the other table's properties here
.where()
.like("route_id", route_id)
.findList();
return trips;
}

Filter nested objects using Jackson's BeanPropertyFilter

I have the following objects:
#JsonFilter("myFilter")
public class Person {
private Name name;
private int age;
public Name getName() {return name;}
public void setName(Name name) {this.name = name;}
public int getAge() {return age;}
public void setAge(int age) {this.age = age;}
}
#JsonFilter("myFilter")
public class Name {
private String firstName;
private String lastName;
public String getFirstName() {return firstName;}
public void setFirstName(String firstName) {this.firstName = firstName;}
public String getLastName() {return lastName;}
public void setLastName(String lastName) {this.lastName = lastName;}
}
I wrote a method to marshall a Person object like this:
#Test
public void test() throws Exception {
Person person = new Person();
person.setAge(10);
Name name = new Name();
name.setFirstName("fname");
name.setLastName("lastname");
person.setName(name);
ObjectMapper mapper = new ObjectMapper();
FilterProvider filters = new SimpleFilterProvider().addFilter("myFilter",
SimpleBeanPropertyFilter.filterOutAllExcept("name.firstName"));
System.out.println(mapper.filteredWriter(filters).writeValueAsString(person));
}
What I'd like to see is JSON like this:
{"name":{"firstName":"fname"}}
Is something like that possible?
Ok, figured it out. Varargs would have made this a bit prettier, but oh well. Just hope I don't have two inner beans which have properties with the same name. I wouldn't be able to make the distinction between the two
FilterProvider filters = new SimpleFilterProvider()
.addFilter("myFilter", SimpleBeanPropertyFilter
.filterOutAllExcept(new HashSet<String>(Arrays
.asList(new String[] { "name", "firstName" }))));
There's a better way that solves problem with property name conflicts. Just add another filter to class Name ("nameFilter"):
#JsonFilter("personFilter")
public class Person {
private Name name;
private int age;
public Name getName() {return name;}
public void setName(Name name) {this.name = name;}
public int getAge() {return age;}
public void setAge(int age) {this.age = age;}
}
#JsonFilter("nameFilter")
public class Name {
private String firstName;
private String lastName;
public String getFirstName() {return firstName;}
public void setFirstName(String firstName) {this.firstName = firstName;}
public String getLastName() {return lastName;}
public void setLastName(String lastName) {this.lastName = lastName;}
}
And then add 2 filters, one for Person and one for Name:
FilterProvider filterProvider = new SimpleFilterProvider()
.addFilter("personFilter", SimpleBeanPropertyFilter.filterOutAllExcept("name"))
.addFilter("nameFilter", SimpleBeanPropertyFilter.filterOutAllExcept("firstName"));