Spring data jpa:QuerySyntaxException: department is not mapped - spring-data-jpa

I am using spring data jpa.I write a query using #query annotation and trying to fetch all columns in a table but while implementing i am getting error that department table is not mapped.
DepartmentsRepository
#Repository
public interface DepartmentsRepository extends JpaRepository<Department, Long>
{
#Query(value = "select d from department d")
public List<Department> findColumns();
}
Department class
#Entity
#Table(name="department")
public class Department
{
#Id
#Column(name="ndept_id")
public int ndept_id;
#Column(name="sdept_name")
public String sdept_name;
#Column(name="ninst_id")
public int ninst_id;
#Column(name="bis_locked")
public boolean bis_locked;
#Column(name="sclient_dept_id")
public String sclient_dept_id;
#Column(name="nsurvey_method_id")
public int nsurvey_method_id;
#Column(name="bis_jointuse")
public boolean bis_jointuse;
#Column(name="ntemp_dept_id")
public int ntemp_dept_id;
#Column(name="balternate_jointuse_percentage")
public boolean balternate_jointuse_percentage;
#Column(name="ndiv_id")
public Integer ndiv_id;

JPQL queries against entities, it won’t affect the database directly. so use model name instead of table name
#Repository
public interface DepartmentsRepository extends JpaRepository<Department, Integer>
{
#Query("select d from Department d")
public List<Department> findColumns();
}

JPA doe not deal with table names, so if you want to write your query in JPA Query Language(JPQL) use fully-classified (package_name.class_name) entity names instead of table names.
So your query will look like this
#Query(value = "select d from package_name.Department d")
public List<Department> findColumns();
Or you can also run plain sql query in the #Query annotation using nativeQuery=true, So your code will look like
#Query(value = "select d from department d", nativeQuery=true)
public List<Department> findColumns();

Related

JPA secodaryTables with composite key

I'm working on a legacy database schema. On this schema there are 2 tables:
clienti 1->many clienti_soc
clienti has the primary key id_cliente, clienti_soc has composite key (id_cliente, id_societa). In my JPA application I need to pick the record of clienti_soc with a specific value of id_societa I'd like to put in my application.properties.
Here how I mapped my entity
#Entity
#Table(name="va_clienti")
#SecondaryTable(name = "va_clienti_soc", pkJoinColumns = #PrimaryKeyJoinColumn(name = "id_cliente"))
#Data
public class Cliente {
#Id
public String idCliente;
public String ragioneSociale;
....
#Column(table = "va_clienti_soc" , name="id_societa")
public String idSocieta = "1"; // <-- ????????
#Column(table = "va_clienti_soc" , name="id_gr_prezzi_partner")
public String idGrPrezziPartner;
}
is there a better way or any best practice to crerate the JPA enity? Is there a cleverer use of #PrimaryKeyJoinColumn annotation?

Convert specific query into JPQL or Criteria Builder query

Here is the code for 2 entities (it generates three tables in the database). A Book entity:
#Entity
public class Book {
#Id
private long id;
private String name;
#ManyToMany
private List<Author> authors;
}
An Author entity:
#Entity
public class Author {
#Id
private long id;
#Column(unique=true)
private String name;
}
I'm trying to find books by the list of authors. Here is a sql query:
select book.id, ARRAY_AGG(author.name)
from book
join book_authors ba on book.id=ba.book_id
join author on ba.authors_id=author.id
group by book.id
having ARRAY_AGG(distinct author.name order by author.name)=ARRAY['a1', 'a2']::varchar[]
['a1', 'a2'] is a list of book authors, it must be passed as a parameter. The idea is to aggregate authors and then compare them with the list of passed parameters.
How to rewrite this SQL-query into either a JPQL or CriteriaBuilder query?
#Query("select distinct b from Book b join b.authors a where a.name in(:names)")
List<Book> findByAuthorsNames(#Param("names") List<String> names)
If you want to fetch b.authors use join fetch instead of join
If the exact match is necessary you can use Specification like this
public class BookSpecifications {
public static Specification<Book> byAuthorsNames(List<String> names) {
return (root, query, builder) -> {
Join<Book, Author> author = root.join("authors", JoinType.LEFT);
Predicate predicate = builder.conjunction;
for(String name : names) {
Predicate namePredicate = builder.and(author.get("name"), name);
predicate = builder.and(predicate, namePredicate);
}
return predicate;
}
}
}
BookRepository have to extend JpaSpecificationExecutor.
Usage:
BookRepository repository;
public List<Book> findByAuthorsNames(List<String> names) {
return repository.findAll(BookSpecifications.byAuthorsNames(names));
}

How to directly get Students list using Spring data jpa #Query annotation

I have two entities: Group and Student which is ManyToMany relation, Group is the owner。
Now define a GroupRepository extends from JpaRepository and want to declare a method using #Query annotation to directly get Student list given a GroupId. How?
The method return value should be List or Page, just no idea how to define using query language.
I know how to get a Group entity with eagerly fetch all Students with that Group like below:
#Query("select group from Group group left join fetch group.students where group.id=:id")
Group findOneWithEagerRelationships(#Param("id") Long id);
Very appreciated for any help.
If you have a model like this:
#Entity
class Group {
#Id Ling id;
#ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private List<Student> students;
//...
}
#Entity
class Student {
#Id Long id;
#ManyToMany(mappedBy = "groups")
private List<Group> groups;
//...
}
Then to get all students through the group repo you can make a method like this:
interface GroupRepo extends JpaRepository<Group, Long> {
#Query("select s from Group g join g.students s where g.id = ?1")
Page<Student> getAllStudentsByGroupId(Long groupId, Pageable pageable);
}
Sources: 1, 2.

Table per concrete class with Hibernate OGM and mongodb

I'm using mongodb to store json documents, and since I'm using Hibernate ORM for my relational models I've decided to use the OGM for the mongo ones.
Currently all of my OGM entities share the same parent class, it looks something like:
#Entity
public abstract class Document {
private static final Gson GSON = new Gson();
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Type(type = "objectid")
protected String id;
public String id() {
return this.id;
}
#Override
public String toString() {
return Document.GSON.toJson(this);
}
}
#Entity
public class Address extends Document {
private String city;
private String street;
private int house;
}
#Entity
public class Person extends Document {
private String name;
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private Set<Address> addresses;
}
(simplified of course)
What I expected that would happen when I persist a Person instance is that two collections will be created in the db, one for Person and the other for Address, which I inferred:
The various inheritance strategies are not supported by Hibernate OGM,
only the table per concrete class strategy is used
(Supported entity mapping - Hibernate OGM documentation)
But what happens in reality is that only one collection is created with the name Document with two documents in it:
{
_id : id1,
DTYPE : Person,
name : name of person
}
{
_id : id2,
DTYPE : Address,
city : City of address,
street : Street of address
house : 3
}
What am I missing?
Thanks
I think, it should be:
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Document {
...
}

Accessing #MappedSuperclass' properties in Criteria Query using metamodel classes

I'm trying to access a property defined in #MappedSuperclass in a Criteria Query with JPA meta-model (Hibernate 4.2.8):
#MappedSuperclass
public class BaseEntity {
private DateTime createdOn;
}
My Entity:
#Entity
#Table(name = "HISTORY")
public class History extends BaseEntity implements Serializable {
private Long id;
}
How to access createdOn?
CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
CriteriaQuery<History> c = cb.createQuery(History.class);
Root<History> h = c.from(History.class);
h.orderBy(cb.asc(a.get(History_.createdOn)));
History_:
#Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor")
#StaticMetamodel(History.class)
public abstract class History_ extends com.test.BaseEntity_ {
public static volatile SingularAttribute<History, Long> id;
}
Is there a way to access base class' properties?
Of course there is a way. As I see in your code, you already access it: History_.createdOn is a property of the MappedSuperclass. If by "to access" you mean to select, than you simply do:
query.select(History_.createdOn)