I have a problem with a QueryDSL query. Classes:
#Entity
#Table(name="project")
#Cacheable(true)
#Cache(usage= CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Project extends DomainObject implements Comparable<Project>, IconizedComponent, Commentable {
#ManyToMany(targetEntity=Student.class)
#JoinTable(name="project_student")
#Sort(type=SortType.NATURAL) //Required by hibernate
#QueryInit({"user"})
private SortedSet<Student> projectParticipants = new TreeSet<Student>();
private Project(){}
//attributes, get+set methods etc
}
#Entity
#Cacheable(true)
#Cache(usage= CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) //Hibernate specific
public class Student extends Role {
public Student(){}
//attributes, get+set methods etc
}
#Entity
#DiscriminatorColumn(name = "rolename", discriminatorType = DiscriminatorType.STRING, length = 8)
#Table(name="role", uniqueConstraints={#UniqueConstraint(columnNames={"user_id","rolename"}, name = "role_is_unique")})
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public abstract class Role extends LazyDeletableDomainObject implements Comparable<Role> {
#ManyToOne(optional=false)
protected User user;
public Role(){}
//attributes, get+set methods etc
}
#Entity
#Table(name="user")
#Cacheable(true)
#Cache(usage= CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) //Hibernate specific
public class User extends LazyDeletableDomainObject implements Comparable<User>, IconizedComponent {
private String firstName;
private String lastName;
public User(){}
//attributes, get+set methods etc
}
Query:
private BooleanExpression authorsNameContains(String searchTerm){
QUser user = new QUser("user");
user.firstName.containsIgnoreCase(searchTerm).or(user.lastName.contains(searchTerm));
QStudent student = new QStudent("student");
student.user.eq(user);
return QProject.project.projectParticipants.contains(student);
//java.lang.IllegalArgumentException: Undeclared path 'student'. Add this path as a source to the query to be able to reference it.
}
I have also tried annotating the projectParticipants set in Project with
#QueryInit("*.*")
But that gives the same exception. Any hints?
#Timo Westkämper
#siebZ0r
Thanks for your attention. Sorry for the delayed reply and incorrectly phrased question. Actually what I wanted to do was to write a working BooleanExpression.
In combination with the annotations already made, this was what I was after:
private BooleanExpression authorsFirstNameContains(String searchTerm){
return QProject.project.projectParticipants.any().user.firstName.containsIgnoreCase(searchTerm);
}
I got this right with the help of a colleague.
Related
I inherited some pretty awful code that I am looking to refactor to make more reusable. There is a set of reporting tables which are primarily composed of 3 columns: id, report_type_fk, and report_description. I would like to merge all the reporting tables into one for ease of use.
I am refactoring the code and think that it would be better to break our current entities up so that Report is an abstract class with type implementations. For example a DmvReport extends Report, CreditScoreReport extends Report, etc.
The problem I am running into is that there would only be 1 report table that all entities would need to save to. Is there a way to make all concrete implementations of the abstract Report object save into the same table?
Here's an example of the bad code I inherited
Report class
#Entity
#Table(name = "report")
public class Report<E extends Exception> {
private long id;
private ReportType type;
private String description;
...
...
}
CreditReport class
#Entity
#Table(name = "credit_report")
public class CreditScore Report<E extends Exception> extends Report<E> {
private long id;
private ReportType type;
private String description;
...
...
}
I am looking to turn it into:
#MappedSuperclass
#Table(name = "report")
public abstract class Report<E extends Exception> {
#Id #Column(name="id")
private long id;
#OneToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "report_type_id")
private ReportType type;
#column(name="description")
private String description;
...
...
}
#Entity
#Table(name = "report")
public class CreditScoreReport<E extends Exception> extends Report<E> {
public void doCreditScoreStuff(){
...
}
}
#Entity
#Table(name = "report")
public class DmvReport<E extends Exception> extends Report<E> {
public void doDmvStuff(){
...
}
}
I think you should use #Inheritance instead of #MappedSuperClass. Your code would look like this:
#Entity
#Table(name = "report")
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name = "report_type_id", discriminatorType = DiscriminatorType.INTEGER)
public abstract class Report<E extends Exception> {
#Id #Column(name="id")
private long id;
#column(name="description")
private String description;
...
...
}
#Entity(name = "CreditScoreReport")
#DiscriminatorValue("1") // the id corresponding to the credit score report
public class CreditScoreReport<E extends Exception> extends Report<E> {
#Column(name = "specific_credit_score_report_1)
private Integer specificCreditScoreReport1;
public void doCreditScoreStuff(){
...
}
}
#Entity(name = "DmvReport")
#DiscriminatorValue("2") // the id corresponding to the DMV report
public class DmvReport<E extends Exception> extends Report<E> {
#Column(name = "specific_dmv_score_report_1)
private Integer specificDmvScoreReport1;
public void doDmvStuff(){
...
}
}
This strategy allows you to store credit score report and DMV report data in one table (report), but instanciate the proper entity according to the report_value_id field. You don't have to define the report_value_id in your parameters because it was already used to create the required entity.
Is this what you're looking for?
I have four classes which should put in one db table.
First class represents basic information.
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name = "TYPE")
#Entity
#JsonInclude(JsonInclude.Include.NON_EMPTY)
public class A {
#Id
private String id;
private LocalDateTime date;
private String someString;
}
The second class extends class a and has some extra properties.
#Inheritance
#MappedSuperclass
#JsonInclude(JsonInclude.Include.NON_EMPTY)
public class B extends A {
private String extraProperty;
}
Finally there are two parallel classes with concrete type information.
#Entity
#DiscriminatorValue(value = "C1")
#JsonInclude(JsonInclude.Include.NON_EMPTY)
public class C1 extends B {
private String property1;
private String property2;
}
#Entity
#DiscriminatorValue(value = "C2")
#JsonInclude(JsonInclude.Include.NON_EMPTY)
public class C2 extends B {
private String propertyX;
private String propertyY;
}
The ReST repository looks like this:
#RepositoryRestResource(
path = "items",
collectionResourceRel = "items"
)
public interface ItemRepository extends PagingAndSortingRepository<A, String> { }
Now I have written a test where the expected format is tested.
#Test
public void shouldReturnItemlistWithCorrectDataStructure() throws Exception {
mockMvc.perform(get("/Items"))
.andExpect(jsonPath("$._embedded.items").isArray())
.andExpect(jsonPath("$._embedded.items", hasSize(2)))
.andExpect(jsonPath("$._embedded.items[0].id").value("1234567"))
...
}
I expected one array (items[]) in the result json but there are actually two different arrays c1[] and c2[].
Any ideas what I'm doing wrong?
I have superclass:
#MappedSuperclass
public abstract class BaseEntity {
#Id #GeneratedValue
private Long id;
#Version
private long version;
}
and two subclasses:
#Entity
#Table(name = "\"user\"")
public class User extends BaseEntity {
private String username;
#org.hibernate.annotations.Type(type = "yes_no")
private boolean isAdmin;
// constructor/getters/setters etc.
}
#Entity
public class Product extends BaseEntity {
public String name;
public BigDecimal price;
// constructor/getters/setters etc.
}
I can query for all subclasses using code:
entityManager.unwrap(Session.class)
.createCriteria(BaseEntity.class)
.list()
.forEach(x -> System.out.println(x));
how I can get the same results via JPA (without unwrap, is it possible?). I tried using createQuery("from BaseEntity") but get BaseEntity not mapped exception.
EDIT: I know that this will result in two SELECT statement. And it must be MappedSuperclass - I would like to not change that.
I'm trying to map a class hierarchy to a single table using Hibernate and one table not creating. I add #Inheritance(strategy=InheritanceType.SINGLE_TABLE) but in base there are separate tables.
#MappedSuperclass
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public abstract class User implements UserDetails {
#Id #GeneratedValue
private int id;
...
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
...
}
#Entity
public class Manager extends User{
...
}
#Entity
public class Administrator extends User{
...
}
Whats wrong?
Your User class should be
#Entity
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(field = "type", discriminatorType = DiscriminatorType.STRING)
public class User implements UserDetails {
/* your original stuff */
}
Then you need to map the extended classes as follows:
#Entity
#DiscriminatorValue("manager")
public class Manager extends User { /* stuff */ }
#Entity
#DiscriminatorValue("administrator")
public class Administrator extends User { /* stuff */ }
This effectively should create a single table which houses all the fields from User, Manager, and Administrator using a special field that is added by Hibernate called type which will hold values of either manager or administrator.
I have my super abstract class :
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class User {
#Id
public int id;
public String name;
}
And two other classes extends User:
Customer
#Entity
#Table(name = "customers")
public class Customer extends User{
#Id
public int id;
public String role;
public Customer(String role){
super();
this.role = role;
}
}
Seller
#Entity
#Table(name = "sellers")
public class Seller extends User{
#Id
#GeneratedValue
public int id;
public String role; // Seller
public Seller(String role){
super();
this.role = role;
}
}
I would like to be able to use the save() method in play, so I wrote this :
public static Result saveCustomer(){
Customer customer = Form.form(Customer.class).bindFromRequest().get();
customer.save();
return ok();
}
But, save() is not defined.
What would be the way to solve this issue ?
Actually... to get the entityManager in play 2.x you hava a Helper.
JPA.em().persist(object);
you can see more information in this link.
save() method is a part of GenericModel which belongs to Play 1.x. Since, you use Play 2.x you should use JPA object and entityManager.persist() method.