I'm using play framework with ebean.
I have 2 classes that share a many-to-many relationship
#Entity
public class profiles extends Model {
#Id
#Column(name = "profile_ID")
public Integer _id;
public String profile;
public String description;
#ManyToMany(cascade = CascadeType.ALL)
public List<role> roles;
......
#Entity
public class role extends Model {
#Id
#Column(name = "role_ID")
public Integer _id;
public String role;
public Integer parent;
public String description;
public Integer sequence;
#ManyToMany(cascade = CascadeType.ALL)
public ArrayList<profiles> prof_ids = new ArrayList<profiles>();
.....
I'm having trouble trying to generate a list containing all the roles that a particular profile has.
could anyone show me how this is done?
You need to provide more information on what specifically you're trying to do.
See below for an action that creates a profile with 2 roles, persists the profile (and roles), finds all profiles, logs the found profiles and their associated roles and then renders them as JSON:
public class Profiles extends Controller {
public static Result create() {
profiles profile = new profiles();
profile.description = "Testing";
profile.profile = "Test Profile";
role role = new models.role();
role.description = "Test Role 1";
role.role = "Role 1";
profile.roles.add(role);
role = new models.role();
role.description = "Test Role 2";
role.role = "Role 2";
profile.roles.add(role);
profile.save();
List<profiles> profiles = Ebean.find(profiles.class).findList();
for (profiles p : profiles) {
Logger.info("Profile: {}", p.profile);
for (role r : p.roles) {
Logger.info("\t-> has role: {}", r.role);
}
}
return ok(Json.toJson(profiles)).as("application/json");
}
}
To get the list of roles, note the reference to p.roles above. Is that what you want?
See here for more advanced queries etc.
Some things to keep in mind:
Always start your class names with a capital letter in Java. The code above is hard to read using your lowercase model/entity names...
Name your entity identifier id not _id, it causes issues when Ebean generates queries.
Related
I have a couple of Hibernate entities stored in a DB that I want to internationalize.
For example my "country" entity:
#Table(name = "country")
public class Country {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false)
private Integer id;
#Column(name = "name")
private String name;
}
What I now want to do is enhance the API that handles the retrieval of the countries to return the country entry in the appropriate language. (e.g. adding ?lang=en to the query)
For that I have a country controller:
#RestController
#Api(tags = "Country")
public class CountryController {
private final CountryDao countryDao;
public CountryController(CountryDao countryDao) {
this.countryDao = countryDao;
}
#ApiOperation(value = "View a list of available countries.")
#GetMapping(path = "/entity/countries")
public Iterable<Country> getCountries() {
return countryDao.findAll();
}
}
How would I do that?
I have thought of adding a new i18n table that holds message keys with the available translations.
But in the end I still would like the API to return a simple JSON entry containing only the country name that the user is interested in, without having to attach all available translations.
I tried with AttributeConverter to mark the fields on the entity with #Convert(converter = I18nConverter.class)and search the i18n table for the matching key, but with that approach I don't have access to the specified language in the query...
public class I18nConverter implements AttributeConverter<String, String> {
private final I18nEntryDao i18nEntryDao;
#Override
public String convertToDatabaseColumn(String attribute) {
...
}
#Override
public String convertToEntityAttribute(String dbData) {
...
}
}
I am developing an app where the user can have one or more roles, for this I decided to created a mapping (intermediate) table, so I ended with User, Role and UserRole like this:
In this app the role(s) a user has determines wheneaver he can access certain views or actions in the frontend. The only thing I need is to retrive the roles a user has and add/delete them. JPA Tools created he following EJB for me (simplified):
USER
/**
* The persistent class for the usuario database table.
*
*/
#Entity
#NamedQuery(name="Usuario.findAll", query="SELECT u FROM Usuario u")
public class Usuario implements Serializable {
private static final long serialVersionUID = 1L;
private int idUsuario;
private List<RolUsuario> rolUsuarios;
public Usuario() {
}
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
public int getIdUsuario() {
return this.idUsuario;
}
public void setIdUsuario(int idUsuario) {
this.idUsuario = idUsuario;
}
//bi-directional many-to-one association to RolUsuario
#OneToMany(mappedBy="usuario")
public List<RolUsuario> getRolUsuarios() {
return this.rolUsuarios;
}
public void setRolUsuarios(List<RolUsuario> rolUsuarios) {
this.rolUsuarios = rolUsuarios;
}
public RolUsuario addRolUsuario(RolUsuario rolUsuario) {
getRolUsuarios().add(rolUsuario);
rolUsuario.setUsuario(this);
return rolUsuario;
}
public RolUsuario removeRolUsuario(RolUsuario rolUsuario) {
getRolUsuarios().remove(rolUsuario);
rolUsuario.setUsuario(null);
return rolUsuario;
}
}
USER_ROLE
/**
* The persistent class for the rol_usuario database table.
*
*/
#Entity
#Table(name="rol_usuario")
#NamedQuery(name="RolUsuario.findAll", query="SELECT r FROM RolUsuario r")
public class RolUsuario implements Serializable {
private static final long serialVersionUID = 1L;
private int idRol_Usuario;
private Usuario usuario;
private Rol rol;
public RolUsuario() {
}
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
public int getIdRol_Usuario() {
return this.idRol_Usuario;
}
public void setIdRol_Usuario(int idRol_Usuario) {
this.idRol_Usuario = idRol_Usuario;
}
//bi-directional many-to-one association to Usuario
#ManyToOne(fetch=FetchType.LAZY)
public Usuario getUsuario() {
return this.usuario;
}
public void setUsuario(Usuario usuario) {
this.usuario = usuario;
}
//bi-directional many-to-one association to Rol
#ManyToOne(fetch=FetchType.LAZY)
public Rol getRol() {
return this.rol;
}
public void setRol(Rol rol) {
this.rol = rol;
}
}
In my project I am using the EJB to create POJO for the frontend. When I ask for the full list of roles for a given user how should I go about doing this:
Create a UserRole repository using CrudRepository with a metod like
List<RolUsuario> findByUsuario(Usuario user);
Return the list of UserRole to my User Service and go over the
the list extracting each Role into a UserPOJO
Send to frontend.
Or is there any way to just get right off the bat a list of Roles in table UserRole where User(Id?) = something?
This is hard to describe for me. My app only cares for the roles of a user, not the mapping table entity, so the botton line is that somehow I have to get them but I don't know where to start.
Any pointers would be extremely useful.
Edit:
Or I could...
Create UserRole for new role addition to a user.
Adding UserRole to the List inside User.
To get the roles of a user get the UserRolelist instead.
Your schema for User and Role is not commonly used. I advice to you make a #ManyToMany association from a user to roles. If you will need to map a join table to the entity (unlikely) you can do it later. And, please, use English identifiers and Java naming convention (idRol_Usuario). It will help you and others.
#Entity
#Table
public class User {
#Id
#GeneratedValue
private Long pid;
#ManyToMany(fetch = FetchType.LAZY)
private List<Role> roles;
}
#Entity
#Table
public class Role {
#Id
private Long pid;
#Column
private String name;
}
You can use Set<Role> too
#ManyToMany(fetch = FetchType.LAZY)
private Set<Role> roles;
The roles of a User and in the rolUsuarios list. In your User service, look up a user, often with the id. If you have the idUsuario, then user EntityManger.find(Usuario.class, idUsuario) and you can read the user roles by getRolUsuarios, or at least that would be the typical way to do it.
In your table design you have a id for the user_role table (iduserrole), which is not typical for a join table. Typically, you just create your entity with a OneToMany annotation and the join table is created for you:
#Entity
public class User {
#Id #GeneratedValue private Long id;
#ManyToMany
Set<Role> roles;
}
and
#Entity
public class Role {
#Id #GeneratedValue private Long id;
}
These two classes would create three tables, the User table, the Role table, and the User_Role Join Table. The join table would have the each id from the user and the role tables in it, and nothing more.
EDIT: The roles is changed to ManyToMany because otherwise a constraint will be added to the database that will prevent the a Role from being added to more than one user. Typically the role table has only unique roles in it, e.g., USER, ADMIN, etc., and so you want to be able to assign them to more than one user.
Is this what you are looking for?
I am new to Neo4J and working with Spring data repository. Following is the domain definition
#NodeEntity
public class Actor {
Long id;
private Set<Role> roles;
}
#RelationshipEntity(type="PLAYED_IN")
public class Role {
#GraphId private Long relationshipId;
#Property private String title;
#StartNode private Actor actor;
#EndNode private Movie movie;
}
#NodeEntity
public class Movie {
private Long id;
private String title;
}
And have GraphRepository defined for each entity class
Following code does not save the RelationshipEntity
Actor actor = new Actor("actorName");
actor = actorRepository.save(actor);
Movie movie = new Movie("movieTitle");
movie = movieRepository.save(movie);
Role role = new Role(actor, movie, "roleTitle");
role = roleRepository.save(role);
Do I have to annotate the roles variable in Actor class?
Do I have to populate roles collection before saving Actor? If I do so then the properties on Role are not saved.
Yes, you must annotate the roles in the Actor entity.
If you're using neo4j-ogm 1.1.3 or an earlier version, make sure that when you create the new role, you add this to the collection of roles in the Actor entity.
If you're using neo4j-ogm 1.1.4-SNAPSHOT, your code should work (after you annotate the roles)
I'm using Ebean with the Play 2 Framework and got two models: a user model and a book model. The user model is connected with the book model in a OneToMany Relationship. So every user can have many books or no book at all. The book model itself has properties too. Now I want to create a query in the user model, which returns only users, who have books with certain properties. For example: One property might be condition, like new or used. Now give me all users which have books in new condition.
Is it possible to create such a query with the Ebean methods? Or do I have to use raw SQL?
Say you have the following models:
#Entity
public class User extends Model {
#Id
#Column(name = "user_index")
private int id;
#Column(name = "user_first_name")
private String firstName;
[...]
#OneToMany(mappedBy = "book_owner_index")
private List<Book> books;
public static Finder<Integer, User> find = new Finder<Integer, User>(Integer.class, User.class);
[...]
}
and
#Entity
public class Book extends Model {
#Id
#Column(name = "book_index")
private int id;
#Column(name = "book_name")
private String name;
#Column(name = "book_condition")
private String condition;
[...]
#ManyToOne
#JoinColumn(name = "book_owner_index", referencedColumnName = "user_index")
private User owner;
[...]
}
Then you can do a search like:
List<User> users = User.find.select("*")
.fetch("books")
.where()
.eq("books.condition", "new")
.findList();
List<User> users = User.find.select("*")
.fetch("books")
.where()
.eq("t1.condition", "new")
.findList();
For me, it works only when I use "t1.", I am using Postgres DB. The generated query makes sense with t1.
I want to search by content on a property in an entity
I have a simple class to define a User:
#Entity
public class User {
#Id
#Column(name = "pers_id")
private int persId;
#Column(name = "full_name")
private String fullName;
#OneToMany
#JoinColumn(name = "PERS_ID")
private List<UserLanguages> languages = new ArrayList<UserLanguages>();
}
A User can have multiple languages, here is the class to make the link between user and a language.
#Entity
public class UserLanguages {
#Column(name="pers_id")
private int persId;
#Id
#Column(name="lang_iso_code")
private String langISO;
#Column(name="lang_full_name")
private String langFullName;
#Column(name="order_seq")
private int order;
}
#Entity
public class Language {
#Id
#Column(name="ID")
private long id;
#Column(name = "CODE")
private String code;
}
I have created a object to do search:
public class UserFilter {
private String name;
private List<Language> languages;
}
I have defined a service:
#Service("userService")
public class UserServiceImpl implements UserService {
#Override
public List<User> findByFilter(UserFilter userFilter) {
final Criteria criteria = userDao.createCriteria();
if (userFilter.getName() != null) {
for (final String token : userFilter.getName().toLowerCase().trim().split(" ")) {
criteria.add(Restrictions.like("fullName", "%" + token + "%"));
}
}
if (null != userFilter.getLanguages() && userFilter.getLanguages().size() > 0) {
final List<String> contents = new ArrayList<String>(userFilter.getLanguages().size());
for (final Language lang : userFilter.getLanguages()) {
contents.add(lang.getCode());
}
criteria.add(Restrictions.in("languages", contents));
}
return userDao.findByCriteria(criteria);
}
My question is how can I do search on languages. I want to find all users with this or thoses languages defined in the userFilter param.
The part about languages doesn't work in the method findByFilter in the service. Can you help me?
First of all, the UserLanguages entity should be named UserLanguage : it represents one language, and not several.
Then, the pers_id column is a foreign key to the User entity. It should thus be mapped as a ManyToOne relationship to the User entity rather than a basic column.
Finally, and to answer your question (I'll assume you want to find the users having at least one user language whose langISO code is in the contents list) : you should use a join :
// inner join between User and UserLanguages
criteria.createAlias("languages", "userLanguage");
// restriction on the langISO property of UserLanguage
criteria.add(Restrictions.in("userLanguage.langIso", contents));