I tried to create a user/roles relation in RDBMS and want to use R2dbc(Spring Data R2dbc) to shake hands with the backend database.
Assume there are three tables, users, roles, and user_roles.
#Table("users")
class User {
#Id
private String username;
private String password;
private String email;
#Builder.Default
private boolean active = true;
#Builder.Default
private List<String> roles = new ArrayList<>();
#Column("created_at")
private LocalDateTime createdDate;
}
Unlike JPA, R2dbc reuses the spring-data-relational-common(which is also used in Spring Data Jdbc) to annotate the tables, but there is no facility to resolve the relations, such as the roles here.
Spring Data R2DBC currently does not support relationships.
So what you would do is to have a separate entity User2Role with two properties: String username and String rolename referencing the ids of the referenced entities.
Since you also tagged the question Spring Data JDBC: Spring Data JDBC does support 1:1 and 1:M references, but not M:1 or M:N relationships. See https://spring.io/blog/2018/09/24/spring-data-jdbc-references-and-aggregates for some background on that.
Spring Data R2DBC might eventually move to the same model.
Related
If I have a table like this :
Client
private Long int;
private String name;
#ManyToOne(mappedBy="otherField")
private Address addresses;
And I Create a repository that extends JPA Repository. Given the name of the client, I want to get as results also the Address Table fields.
Using the method
Client findByName(String name)
Will my this also return all the fields that are on the Address Table ?
Like:
Address
private Long id;
private String city;
private Int code;
private String street;
From the docs
The Hibernate recommendation is to statically mark all associations
lazy and to use dynamic fetching strategies for eagerness. This is
unfortunately at odds with the JPA specification which defines that
all one-to-one and many-to-one associations should be eagerly fetched
by default. Hibernate, as a JPA provider, honors that default.
So Hibernate behaves the same as JPA:
OneToMany: LAZY
ManyToOne: EAGER
ManyToMany: LAZY
OneToOne: EAGER
Also take a look at the JPA sepcifications here.
Let's suppose we have an Entity of this type:
#Entity
#Table(name="User")
public class User {
#Id
long id;
#ElementCollection
List<String> phones;
}
My goal is to have the complete list of phones, for all users, something like: "SELECT x.phones FROM User x"
I tried to build a Spring Data JPA query of this kind:
#Query("SELECT x.phones FROM User x")
List<String> findAllPhones();
But I get this exception:
org.hibernate.QueryException: not an entity
at org.hibernate.hql.internal.ast.tree.FromElementType.renderIdentifierSelect(FromElementType.java:188)
I had to resort to a native sql query to solve the problem.
Otherwise I have to wrap the phone number inside a new Entity, but I exactly want to avoid that.
Is there any way to solve this kind of problem using plain JPA or (even better) only Spring Data JPA methods?
working with OpenJPA2 persistence. I have a very simple entity class, that does have a String property and a List property. I do persist its instances flawlessly with the nested List (in a JSF2 web project). I check the database and there appears two tables (I use automatic schema generation), one for the entity itself, and other table for the nested List. All data persisted using EntityManager is stored fine on both tables.
Problem is I cannot retrieve nested data. I mean, I do a Query for getting all instances of the entity, but the List of all instances come empty.
(DB Engine is MySQL. ORM is OpenJPA2. Server is TomEE 1.6. IDE is Netbeans 8. I use automatic schema generation, so I DO NOT WANT to design the database tables, and I DO WANT to let the ORM create the tables, so I can work purely with objects and forget about DB.)
following is Entity Class code:
#Entity
public class Cliente implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String nombre;
#ElementCollection
private List<String> emails = new ArrayList<String>();
// getters and setters omitted for brevity.
It does have an associated Facade Class, which is ClienteFacade. It includes the getAll method which uses a JPQL Query.
public List<Cliente> listaClientes(){
Query query = em.createQuery("SELECT c FROM Cliente c");
return query.getResultList(); }
Problem is, I get all instances of the entity in a List, but all lists of List emails come out empty. I think problem may be in the JPQL query. Still trying to learn JPQL with some difficulty... so please, How can I retrieve the nested data with JPQL?
Many thanks!
Try #ElementCollection(fetch = FetchType.EAGER) because the default type is lazy. That means that the lists are not loaded directly.
My requirement is to have few custom fields in the domain objects. These fields may vary as per the clients.
We are using Spring Data JPA to execute finders. Spring data implicitly provides finders for static fields of the domain and can also handle finders for the fields in the object graph.
I want to know if there is a way to find data on the custom fields? Can someone suggest me a strategy to achieve the same. Below is the sample of my domain class.
public class Employee{
private String name;
private String age;
private Map customeFields; (May vary as per client)
}
I was thinking of overriding QueryLookupStrategy and create my CustomJpaQuery on lines of PartTreeJpaQuery to achieve it. Is there any better approach? Does spring data jpa provides an easy mechanism to override query creation mechanism?
If you are using hibernate (not sure about other JPA implementations) you may add methods with #Query annotations like this:
#Query("select e from Employee as e where e.customeFields[:key] = :value")
List<Employee> findSomeHow(#Param("key") String key, #Param("value") String value)
package example;
...
#Entity
#Indexed
public class Book {
#Id
#GeneratedValue
private Integer id;
#Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO)
private String title;
#Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO)
private String subtitle;
#Field(index = Index.YES, analyze=Analyze.NO, store = Store.YES)
#DateBridge(resolution = Resolution.DAY)
private Date publicationDate;
#IndexedEmbedded
#ManyToMany
private Set<Author> authors = new HashSet<Author>();
#OneToMany(mappedBy="book")
List<BookPages> bookPages;
}
1) If the search result is of type Book.class does the result contain #ManyToOne objects (bookPages) or do I have to load them separately? Because I need them for showing the result.
2) Is it possible to add a native sql clause to the search? Because I need to limit the result and for that I have to JOIN another table which is not declared in Book.class.
That is a basic Hibernate ORM question, not related to Hibernate Search. Yes you can always navigate from one entity to its relations by just invoking the getter / accessing the fields: depending on your (configurable) fetch strategy it will either have the relation preloaded in "one shot" when loading the main entity (likely with a JOIN) or fetch it transparently on demand. This configuration is however not have any effect on functionality, more a performance tuning option.
No you can't mix SQL with an Hibernate Search (Fulltext) query; what you can do is to expose the needed data from the other table in the mapping - which would be a cleaner mapping anyway - and then use the Hibernate Search annotations to make sure all fields you need are indexed as well, so that you can include the restrictions in the FullTextQuery directly; fill perform much faster as well than any SQL.
It is not possible to mix native SQL with hibernate search query, as there is no way to intersect the results from both queries without iterating on at least one of the results.
See the documentation reference about this exact question.
Hibernate Search - FAQ - Can I mix HQL and Lucene queries?
http://hibernate.org/search/faq/