I am using the productid as a foreign key in my phone table. I don't know what to write in the id part of the PhoneRepository. Because gives an error
Product.java
#Entity
#Data
#AllArgsConstructor
#NoArgsConstructor
public class Product {
#Id #GeneratedValue(strategy = GenerationType.IDENTITY)
private long productID;
...
Phone.java
#Entity
#Data
#AllArgsConstructor
#NoArgsConstructor
#IdClass(Product.class)
public class Phone implements Serializable{
private static final long serialVersionUID = 1L;
#Id
#OneToOne
#JoinColumn(name = "productID")
private Product product;
...
PhoneRepository.java
#Repository
public interface PhoneRepository extends CrudRepository<Phone, Product>{ //I tried Long
}
Error
Caused by: java.lang.IllegalArgumentException: This class [class
com.test.project.data.entity.prod.Phone] does not define an IdClass
Remove the #IdClass annotation on Product because you are not customizing an id provider.
Also remove #Id from product on Phone and add a phoneID as below:
#Id
private long phoneID;
#OneToOne
#JoinColumn(name = "productID", referencedColumnName = "productID")
private Product product;
Related
Currently I have two entities, Hoa and Activity respectively. They share the following relationship
HOA:
#Data
#Entity
#Builder
#AllArgsConstructor
#NoArgsConstructor
public class Hoa {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotNull
#Builder.Default
#OneToMany(mappedBy = "hoa", orphanRemoval = true)
#Cascade(CascadeType.ALL)
#Where(clause = " time > now() ")
private List<Activity> activityDashboard = new ArrayList<>();
Activity:
#Data
#Builder
#Entity
#NoArgsConstructor
#AllArgsConstructor
#Where(clause = "time > now()")
public class Activity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotNull
#Builder.Default
private LocalDateTime time = LocalDateTime.now();
#NotNull
#ManyToOne
#JoinColumn(name = "HOA_ID")
#JsonIgnore
#ToString.Exclude
private Hoa hoa;
}
The use of #Where here suggests two things:
1.) When I try to get the associated activity entity from the repository directly it should not return anything.
2.) When I get the HOA entity from the repository, it should also not have the associated activity object within the list.
With this being said, The last assertion in the following test is failing.
#Test
void lateActivitiesShouldNotBeDisplayed() {
Activity sut = activityService.createActivity(activityInThePast,1L);
assertThat(activityRepository.findAll()).isEmpty();
Hoa sutHoa = hoaRepository.findById(sut.getHoa().getId()).get();
assertThat(sutHoa.getActivityDashboard()).isEmpty();
}
The sutHoa object has the associated activity within the activityDashboard list. Why could this be happening?
I have setup two entities like below in a one-to-one mapping and I am trying to query on the joincolumn like below in my repository:
#Entity
#Table(name = "a")
#AllArgsConstructor
#NoArgsConstructor
#Data
#EqualsAndHashCode(callSuper=false)
public class A extends Auditable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(unique = true)
#Size(min = 1, max = 100)
private String name;
}
#Entity
#Table(name = "b")
#AllArgsConstructor
#NoArgsConstructor
#Data
#EqualsAndHashCode(callSuper=false)
public class B extends Auditable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column
#Size(min = 1, max = 100)
private String name;
#OneToOne
#JoinColumn(name="aId", referencedColumnName = "aId")
private A aId;
}
In my BRepository.java, I am trying to do this:
#Component
public interface BRepository extends JpaRepository<B, Long> {
List<B> findAllBByA_aId(String aId);
}
I get the following error:
No property a found for type B! Did you mean 'aId'?
Is this not the right way to query on a join column in spring-data??
Since you have not defined the column name for id in A then the column name will defaults to id. Then in class B, you should change the referencedColumnName to id (or else you can simply skip the referencedColumnName attribute since it can be derived directly from the target entity in an OneToOne relationship)
#Entity
#Table(name = "b")
#AllArgsConstructor
#NoArgsConstructor
#Data
#EqualsAndHashCode(callSuper=false)
public class B extends Auditable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column
#Size(min = 1, max = 100)
private String name;
#OneToOne
#JoinColumn(name="aId", referencedColumnName = "id")
private A aId;
}
In repository, you need to annotate it with #Repository annotation to let Spring know it should be treated as a Repository Bean.
#Repository
public interface BRepository extends JpaRepository<B, Long> {
#Query(value="select b from B b where B.aId.id=?1")
List<B> findAllBByA_aId(String aId);
}
or you can use SPeL directly,
#Repository
public interface BRepository extends JpaRepository<B, Long> {
List<B> findAllByaIdId(String aId);
}
I have two tables that I want to join.
Lets say TableA and TableB.
TableA
#Entity
#Table(name = "TableA")
#Data
#Builder
#AllArgsConstructor
#NoArgsConstructor
public class TableA {
#Id
#EmbeddedId
private TableA.PrimaryId id = new TableA.PrimaryId();
#Column(name = "COL1")
private Integer col1;
#ManyToOne
#JoinColumn(name = "ID1")
private TableB tableB;
#Data
#Embeddable
#Builder
#AllArgsConstructor
#NoArgsConstructor
public static class PrimaryId implements Serializable {
#Column(name = "ID1")
private Integer id1;
#Column(name = "ID2")
private Integer id2;
}
}
TableB
#Entity
#Table(name = "TableB")
#Data
#Builder
#AllArgsConstructor
#NoArgsConstructor
public class TableB {
#Id
#EmbeddedId
private PrimaryId id = new PrimaryId();
#Column(name = "COLUMN1")
private String column1;
#Data
#Embeddable
#Builder
#AllArgsConstructor
#NoArgsConstructor
public static class PrimaryId implements Serializable {
#Column(name = "ID1")
private Integer id1;
#Column(name = "KEY2")
private Integer key2;
#Column(name = "KEY3")
private Integer key3;
#Column(name = "KEY4")
private Long key4;
}
}
The problem is that TableB has composite primary key (4 columns), but I need to do join only on 1 column (ID1).
It isnt a standart join, it is a partial primary key join.
So it causes an error:
nested exception is org.hibernate.AnnotationException: A Foreign key refering TableB from TableA has the wrong number of column. should be 4
If I try this
#ManyToOne
#JoinColumn(name = "ID1", referencedColumnName = "ID1", updatable=false, insertable=false)
I get another error
nested exception is org.hibernate.AnnotationException: referencedColumnNames(ID1) of TableA.TableB referencing TableB not mapped to a single property
I've looked for an answer in similar posts but found nothing useful :(
So I appreciate any help...
I am using hibernate one to one mapping between car and person table. But a person might have car and might not have a car. now while fetching the records from the person table using hibernate criteria , I want to fetch only those persons who have a car, i.e only those entries in person table for which a corresponding entry in car table exists. How this can be done using hibernate criteria/alias?
Below is the piece of code. kindly help with the criteria or alias that has to written to fetch result:
#Getter
#Setter
#Entity
#Table(name = "Person")
public class Person implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "Person_ID")
private Long personId;
#OneToOne(mappedBy = "personAsset", cascade = CascadeType.ALL)
private Car car;
}
#Getter
#Setter
#Entity
#Table(name = "Car")
public class Car implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "Car_ID")
private Long carId;
#OneToOne
#JoinColumn(name = "Person_ID")
private Person personAsset;
}
what you are looking for is the cascadeType orphanRemoval=true on the #OneToOne annotation.
here is your class how would look like :
#Getter
#Setter
#Entity
#Table(name = "Car")
public class Car implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "Car_ID")
private Long carId;
#OneToOne(fetch=FetchType.EAGER , cascade=CascadeType.ALL, orphanRemoval=true)
#JoinColumn(name = "Person_ID")
private Person personAsset;
}
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Person> query = cb.createQuery(Person.class);
Root<Person> person = query.from(Person.class);
Predicate predicate = cb.isNotNull(person.join("car"));
predicates.add(predicate );
Used this as my base point: https://vladmihalcea.com/the-best-way-to-map-a-many-to-many-association-with-extra-columns-when-using-jpa-and-hibernate/
I have an entity named Attendance that has an and emebedid AttendacneId that has two columns lectureId (string) and studenId(UUID). The attendance entity also has other properties as well containing a ManyToOne relationship with student and lecture enity using the #MapsId on them. The student extends user entity where the id resides. now when I try to save anything I get this error.
java.util.NoSuchElementException
at java.util.ArrayList$Itr.next(ArrayList.java:860)
at org.hibernate.cfg.annotations.TableBinder.linkJoinColumnWithValueOverridingNameIfImplicit(TableBinder.java:724)
at org.hibernate.cfg.PkDrivenByDefaultMapsIdSecondPass.doSecondPass(PkDrivenByDefaultMapsIdSecondPass.java:37)
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1684)
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1641)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:286)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.build(MetadataBuildingProcess.java:83)
at org.hibernate.boot.internal.MetadataBuilderImpl.build(MetadataBuilderImpl.java:473)
at org.hibernate.boot.internal.MetadataBuilderImpl.build(MetadataBuilderImpl.java:84)
at utility.Utils.<clinit>(Utils.java:60)
at utility.Testing.main(Testing.java:21)
My AttendanceId class
#Embeddable
public class AttendanceId implements Serializable {
#Column(name = "lecture_fid")
#Getter
#Setter
private String lectureId;
#Column(name = "student_fid", columnDefinition = "uuid")
#Getter
#Setter
private UUID studentId;
public AttendanceId() {}
}
My Attendance class
#Entity
#Table(name = "attendance")
public class Attendance implements Serializable {
#EmbeddedId
#Getter
#Setter(AccessLevel.PRIVATE)
private AttendanceId id;
// other fields
#ManyToOne(fetch = FetchType.LAZY)
#MapsId("lectureId")
private Lecture lecture;
#ManyToOne(fetch = FetchType.LAZY)
#MapsId("studentId")
private Student student;
}
My Student Class
#Entity
#PrimaryKeyJoinColumn(name = "id")
public class Student extends User implements Serializable,
Comparable<Student> {
// other fields
#OneToMany(mappedBy = "student", fetch = FetchType.LAZY)
#Getter
private List<Attendance> attendances = new ArrayList<>();
}
My User class
#Entity
#Table(name = "users", uniqueConstraints = {
#UniqueConstraint(columnNames = {"email", "username"})})
#Inheritance(strategy = InheritanceType.JOINED)
public abstract class User implements Serializable {
#Id
#GeneratedValue(generator = "uuid")
#GenericGenerator(name = "uuid", strategy = "uuid")
#Column(columnDefinition = "UUID")
#Getter(AccessLevel.PUBLIC)
#Setter(AccessLevel.PUBLIC)
private UUID id;
// other fields.
}
My Lecture Class
#NamedNativeQueries(
#NamedNativeQuery(name = "getLectureId", query = "select
get_lecture_id()")
)
#Entity
#Table(name = "lecture")
public class Lecture implements Serializable {
#Id
#Column(name = "id")
#GenericGenerator(name = "lectureIdGenerator",
strategy = "entities.LectureIdGenerator")
#GeneratedValue(generator = "lectureIdGenerator")
#Getter
#Setter
private String id;
#OneToMany(mappedBy = "lecture", fetch = FetchType.LAZY)
#Getter
private List<Attendance> attendances = new ArrayList<>();
// other fields
}
I think the inheritance is causing an issue. There are other classes/entities as well that extends the user entity. If anyone could help me find the problem that will be great. Thank you.
This issue is caused by the HHH-7135 Hibernate issue.