I have a SQL query like this:
"Select UIProfileID from UserTable where UPPER(UserID) = UPPER('?1')".
I want to convert it to Spring JPA.
I want to write getUIProfileId() and return Integer. But I don't know how to implement. Because User table doesn't have UIProfileId column that it was joined from UIProfileTable table. Please help me solve it.
Currently, I have tables:
User.java
#Entity
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#Builder
#Table(name = "UserTable")
public class User {
#Column(name = "UserID", length = 32, nullable = false)
#Id
private String name;
#ManyToOne
#JoinColumn(name = "DomainID", nullable = false)
private Domain domain;
#Column(name = "Password", length = 32, nullable = false)
private String password;
#ManyToOne
#JoinColumn(name = "UIProfileID", nullable = false)
private UIProfile uiProfile;
#Column(name = "ResPerpage", nullable = false)
private Integer resperpage;
#Column(name = "DefaultTab")
private Integer defaulttab;
#ManyToOne
#JoinColumn(name = "AdminProfile")
private AdminProfiles adminProfile;
#Column(name = "LanguageId")
private Integer languageId;
}
UIProfile.java
#Entity
#Getter
#Setter
#Table(name = "UIProfileTable")
public class UIProfile implements Serializable {
#Id
#Column(name = "UIProfileID", length = 11, nullable = false)
private Integer id;
#Column(name = "UIProfileName", length = 32, nullable = false)
private String name;
#OneToMany(mappedBy = "id.uiProfile")
private List<UIProfileTopLevel> topLevels;
}
UserRepository.java
public interface UserRepository extends Repository<User, String> {
Optional<User> findOne(String name);
#Query("Select UIProfileID from User where UPPER(UserID) = UPPER('admin')")
Integer getUIProfileId();
}
You can try this:
#Query("SELECT u.uiProfile.id from User u where UPPER(u.name)=UPPER('admin')")
Integer getUIProfileId();
Here User is the domain class name and u is the reference of User. with u we will access User's field NOT the column name which are specified with #Column or #JoinColumn Ex : #JoinColumn(name = "UIProfileID", nullable = false).
Related
I tried several solutions to my SQL query but it seems like I miss something.
I want to get a List<Product> from a nativeQuery.
And I have a relationship between my User entity and Product entity as One to Many.
Here is my both entites -> Product
#Entity
#Data
#Table(name = "product")
#NoArgsConstructor
#AllArgsConstructor
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#CreationTimestamp
#Column(updatable = false)
private Timestamp createdDate;
#UpdateTimestamp
private Timestamp lastModifiedDate;
private String imageURL;
private Long productCode;
#Size(min = 3,max = 100)
private String productName;
#Size(min = 5,max = 100)
private String details;
private BigDecimal price;
private ProductCategory productCategory;
}
User ->
#Data
#AllArgsConstructor
#NoArgsConstructor
#Entity
#Table(name = "users")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(unique = true,nullable = false)
private String phoneNumber;
#Size(min = 5, max = 25, message = "Username length should be between 5 and 25 characters")
#Column(unique = true, nullable = false)
private String userName;
#CreationTimestamp
#Column(updatable = false)
private Timestamp createdDate;
#UpdateTimestamp
private Timestamp lastModifiedDate;
#Column(unique = true, nullable = false)
#NotNull
private String email;
#Size(min = 5, message = "Minimum password length: 5 characters")
#NotNull
private String password;
#OneToMany(fetch = FetchType.LAZY,cascade = CascadeType.ALL,orphanRemoval = true)
private List<Product> products;
#Transient
#OneToMany(fetch = FetchType.LAZY,mappedBy = "product",cascade = CascadeType.ALL,orphanRemoval = true)
private List<ProductInquiry> productInquiries;
private Role role;
}
Here in this query I need to return all products associated with the given user_id.
#Query(value = "SELECT new egecoskun121.com.crm.model.entity.Product(p.ID,p.CREATED_DATE,p.LAST_MODIFIED_DATE,p.IMAGEURL,p.PRODUCT_CODE,p.PRODUCT_NAME,p.DETAILS,p.PRICE,p.PRODUCT_CATEGORY) FROM PRODUCT AS p WHERE {SELECT PRODUCT_ID FROM USERS_PRODUCTS WHERE USER_ID=:id }",nativeQuery = true)
List<Product> findAllProductsById(#Param("id")Long id);
The problem is that you are using a HQL query but you've set native=true. Setting native=true means that you want to run a SQL query.
This HQL query should work:
#Query("select p from User u join u.products p WHERE u.id = :id")
List<Product> findAllProductsById(#Param("id")Long id);
I have two java entity classes :
#Table(name = "user")
public class UserEntity
{
#Id
#Column(name = "id", unique = true, nullable = false)
private Long id;
#OneToOne(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
#JoinColumn(name = "opportunity_id")
private OpportunityEntity opportunity;
}
and
#Table(name = "opportunity")
public class OpportunityEntity
{
#Id
#Column(name = "id", unique = true, nullable = false)
private Long id;
#OneToMany
#JoinColumn(name = "opportunity_id")
private List<UserEntity> users;
#OneToOne
#JoinColumn(name = "mainuser_id")
private UserEntity mainUser;
}
When i search for a list of Users [find users], i've got a "stackoverflow" when mapping User.opportunity.
the bug was clear that the opportunity.mainUser refer to User which itself refer to the same opportunity.
Is there another way to design my models ?
For example create a boolean isMain in User Model ?
Try to specify relationship to UserEntity by adding mappedBy to annotatation
#Table(name = "opportunity")
public class OpportunityEntity
{
#Id
#Column(name = "id", unique = true, nullable = false)
private Long id;
#OneToMany
#JoinColumn(name = "opportunity_id")
private List<UserEntity> users;
#OneToOne(mappedBy="opportunity")
#JoinColumn(name = "mainuser_id")
private UserEntity mainUser;
}
Trying to get value from 2 joined tables with getter, have 2 models Customer and Address.
#Setter
#Getter
#Data
#Entity
#Accessors(chain = true)
#Table(name = "customer")
public class Customer implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "id", nullable = false)
private Long id;
#Column(name = "name")
private String name;
#Column(name = "phoneNumber")
private String phoneNumber;
#Column(name = "address")
private String address;
}
#Setter
#Getter
#Data
#Entity
#Accessors(chain = true)
#Table(name = "address")
public class Address implements Serializable {
#Id
#Column(name = "id", nullable = false)
private Long id;
#Column(name = "address")
private String address;
#Column(name = "zipcode")
private String zipcode;
#Column(name = "number")
private Integer number;
#ManyToOne
#JoinColumn(name="customer")//
private Customer customerBean;
}
Address Repository with this query :
#Query( value = "SELECT ad FROM Address ad, Customer c WHERE ad.customer = c.id and c.id = 1)
Optional <List<Address>> getAddress();
Try to get with getter :
Optional<List<Address>> address = getAddress();
System.out.println(address.getAddress()); //success
System.out.println(address.getAddress().get().get(0).getCustomerBean().getName()) //null value
Successfully get data address from table Address, but if get Customer name get null value, any suggestion?
Try the following in your #Query definition:
#Query(value = "SELECT ad FROM Address ad JOIN FETCH ad.customer WHERE ad.customer = 1")
Optional <List<Address>> getAddress();
I have tried to create some JPA Entities for a DB designed with the following tables: PRINCIPALS and CREDENTIALS which have the following relations with other tables:
#Entity
#Table(name = "CREDENTIALS")
public class Credentials {
#Id
#Column(name = "CREDENTIAL_ID")
private Integer credentialID;
#Id
#Column(name = "CREDENTIAL_TYPE_ID")
private String credentialTypeID;
#OneToOne
#JoinColumn(name = "CREDENTIAL_TYPE_ID", insertable = false, updatable = false)
private CredentialTypes credentialTypes;
}
CREDENTIALS has a oneToOne relation with CREDENTIAL_TYPES
#Entity
#Table(name = "CREDENTIAL_TYPES")
public class CredentialTypes {
#Id
#Column(name = "CREDENTIAL_TYPE_ID")
private String credentialTypeID;
#Column(name = "DESCRIPTION")
private String description;
}
#Entity
#Table(name = "PRINCIPALS")
public class Principals implements Serializable {
#Id
#Column(name = "PRINCIPAL_TYPE_ID", nullable = false)
private String principalTypeID;
#Column(name = "PRINCIPAL_ID", nullable = false)
private String principalID;
#OneToOne
#JoinColumn(name = "PRINCIPAL_TYPE_ID", insertable = false, updatable = false)
private PrincipalTypes principalTypes;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinTable(name = "PRINCIPAL_CREDENTIAL",
joinColumns = #JoinColumn(name = "CREDENTIAL_ID"),
inverseJoinColumns = #JoinColumn(name = "PRINCIPAL_ID"))
private List<Credentials> credentials;
PRINCIPALS has a oneToOne relation with PRINCIPAL_TYPES
#Entity
#Table(name = "PRINCIPAL_TYPES")
public class PrincipalTypes implements Serializable {
#Id
#Column(name = "PRINCIPAL_TYPE_ID", nullable = false)
private String principalTypeID;
#Column(name = "DESCRIPTION")
private String description;
And finally PRINCIPALS has a oneToMany relation with CREDENTIALS and uses a join table PRINCIPLE_CREDENTIAL
#Entity
#Table(name = "PRINCIPAL_CREDENTIAL")
public class PrincipalCredential implements Serializable {
#Id
#Column(name = "PRINCIPAL_TYPE_ID", nullable = false)
private String principalTypeID;
#Id
#Column(name = "PRINCIPAL_ID", nullable = false)
private String principalID;
#Id
#Column(name = "CREDENTIAL_ID")
private Integer credentialID;
#Id
#Column(name = "CREDENTIAL_TYPE_ID")
private String credentialTypeID;
At startup (using SpringBoot) I receive an error for the oneToMany relation between Principals and Credentials and just don't have any idea how to fix it... Tried various other methods (The DB design cannot be changed).
Caused by: org.hibernate.AnnotationException: A Foreign key refering entities.Principals from entities.Credentials has the wrong number of column. should be 2
at org.hibernate.cfg.annotations.TableBinder.bindFk(TableBinder.java:502)
at org.hibernate.cfg.annotations.CollectionBinder.bindCollectionSecondPass(CollectionBinder.java:1467)
at org.hibernate.cfg.annotations.CollectionBinder.bindManyToManySecondPass(CollectionBinder.java:1233)
at org.hibernate.cfg.annotations.CollectionBinder.bindStarToManySecondPass(CollectionBinder.java:794)
at org.hibernate.cfg.annotations.CollectionBinder$1.secondPass(CollectionBinder.java:729)
at org.hibernate.cfg.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:70)
at org.hibernate.cfg.Configuration.originalSecondPassCompile(Configuration.java:1697)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1426)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1846)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:85
I find the exception wierd because there is no refering of Principlas from Credentials....
PRINCIPLE_TYPE_ID and CREDENTIAL_TYPE_ID are missing in the joinColumns/inverseJoinColumns. I think you must use the #JoinColumns Annotation
I've creating entities from a data-source using Netbeans 7.4.
And I have an error which arises with all entities which have a composite primary key. The error can be seen below.
I have searched this problem on stack-overflow and its is usually because people have not defined the join columns. but I have this done. I'm also unsure how there is errors in code generated by netbeans.
Here is an image of my MySQL database which I forward engineered to create these entitys:
Any help would be greatly appreciated !
Here is the only the relevant code
Absence entity:
public class Absence implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected AbsencePK absencePK;
#Basic(optional = false)
#NotNull
#Column(name = "idAbsence")
private int idAbsence;
#Basic(optional = false)
#NotNull
#Column(name = "Date")
#Temporal(TemporalType.DATE)
private Date date;
#Size(max = 35)
#Column(name = "type")
private String type;
#Lob
#Size(max = 65535)
#Column(name = "remark")
private String remark;
#JoinColumn(name = "TimeTable_Period", referencedColumnName = "Period", insertable = false, updatable = false)
#ManyToOne(optional = false)
private Timetable timetable;
#JoinColumn(name = "Student_idStudent", referencedColumnName = "idStudent", insertable = false, updatable = false)
#ManyToOne(optional = false)
private Student student;
#JoinColumn(name = "Class_idClass", referencedColumnName = "idClass", insertable = false, updatable = false)
#ManyToOne(optional = false)
private Class class1;
AbsencePK entity:
#Embeddable
public class AbsencePK implements Serializable {
#Basic(optional = false)
#NotNull
#Column(name = "Class_idClass")
private int classidClass;
#Basic(optional = false)
#NotNull
#Column(name = "Student_idStudent")
private int studentidStudent;
#Basic(optional = false)
#NotNull
#Column(name = "TimeTable_Period")
private int timeTablePeriod;
public AbsencePK() {
}
public AbsencePK(int classidClass, int studentidStudent, int timeTablePeriod) {
this.classidClass = classidClass;
this.studentidStudent = studentidStudent;
this.timeTablePeriod = timeTablePeriod;
}
Error:
Caused by: Exception [EclipseLink-7220] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b):
org.eclipse.persistence.exceptions.ValidationException
Exception Description: The #JoinColumns on the annotated element [field timetable] from the entity class [class com.fyp.simstest.Absence] is incomplete.
When the source entity class uses a composite primary key, a #JoinColumn must be specified for each join column using the #JoinColumns.
Both the name and the referencedColumnName elements must be specified in each such #JoinColumn.
at org.eclipse.persistence.exceptions.ValidationException.incompleteJoinColumnsSpecified(ValidationException.java:1847)
EDIT
TimeTable
#Entity
#Table(name = "timetable")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Timetable.findAll", query = "SELECT t FROM Timetable t"),
#NamedQuery(name = "Timetable.findByPeriod", query = "SELECT t FROM Timetable t WHERE t.timetablePK.period = :period"),
#NamedQuery(name = "Timetable.findByDay", query = "SELECT t FROM Timetable t WHERE t.timetablePK.day = :day"),
#NamedQuery(name = "Timetable.findByClassidClass", query = "SELECT t FROM Timetable t WHERE t.timetablePK.classidClass = :classidClass")})
public class Timetable implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected TimetablePK timetablePK;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "timetable")
private Collection<Absence> absenceCollection;
#JoinColumn(name = "Class_idClass", referencedColumnName = "idClass", insertable = false, updatable = false)
#ManyToOne(optional = false)
private Class class1;
public Timetable() {
}
public Timetable(TimetablePK timetablePK) {
this.timetablePK = timetablePK;
}
TimetablePK
Embeddable
public class TimetablePK implements Serializable {
#Basic(optional = false)
#NotNull
#Column(name = "Period")
private int period;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 45)
#Column(name = "Day")
private String day;
#Basic(optional = false)
#NotNull
#Column(name = "Class_idClass")
private int classidClass;
public TimetablePK() {
}
public TimetablePK(int period, String day, int classidClass) {
this.period = period;
this.day = day;
this.classidClass = classidClass;
}
EDIT TWO
Your diagram indicates the TimeTable table has a primary key composed of three columns (Period, Day, and Class_idClass). You will need to add an annotation to Absence.timeTable that looks something like this:
public class Absence implements Serializable {
...
#JoinColumns[
#JoinColumn(name = "TimeTable_Period", referencedColumnName = "Period", ...),
#JoinColumn(name = "????", referencedColumnName = "Day", ...),
#JoinColumn(name = "Class_idClass", referencedColumnName = "Class_idClass", ...)
]
#ManyToOne(optional = false)
private TimeTable timeTable;
...
}
Consider this:
#JoinColumn(name = "TimeTable_Period", referencedColumnName = "Period")
private Timetable timetable;
You have referenced to the column Period at your Timetable entity. But in the Timetable.java I don't see any field that is mapped with your Period column of your table.
For example:
#Id // as its the primary key!
#Column(name="Period")
private Long period
This should be same for other referenced entities those you have used with your #ManyToOne mapping.