I have a Student model class, and one of the entities is a List of courses offered by the student. when a sudent account is created, it is created with some courses, but this would need to be updated every semester. I want to update that column to add a new course but I don't know how to do that. I tried a SQL update query, but that just changes the values. I'm not very good with SQL and I would like to know if there's any other way to achieve this.Here's my model class.
#Data
#AllArgsConstructor
#NoArgsConstructor
public class Student {
#Id
private int studentId;
#JsonProperty
private String name;
#JsonProperty
private String email;
#JsonProperty
private String department;
#JsonProperty
private int level;
#JsonProperty
private double cgpa;
#JsonProperty
#ManyToMany
private List<Course> coursesOffered;
Related
I have one to many relationship. If in class Customer I write List:
private List<Orders> order;
my GetMapping will work fine.
But I want to use best practices and I write Set instead of List:
private Set<Orders> order;
In result I have error:
Could not write JSON: Infinite recursion (StackOverflowError); nested
exception is com.fasterxml.jackson.databind.JsonMappingException:
Infinite recursion (StackOverflowError)
Why I have this error? What's wrong with Set?
My entities:
#Entity
public class Customer {
#Id
#GeneratedValue
private int id;
private String firstName;
private String lastName;
#OneToMany(cascade=ALL, mappedBy="customer", orphanRemoval=true)
private Set<Orders> order;
//private List<Orders> order;
}
#Entity
public class Orders {
#Id
#GeneratedValue
private int id;
#JsonIgnore
#ManyToOne
#JoinColumn(name="customer_id", nullable=false)
private Customer customer;
}
And GetMapping:
#GetMapping("/customer/{id}")
public ResponseEntity get(#PathVariable Long id) {
Optional<Customer> customer = customerRepository.findById(id);
return new ResponseEntity<>(new ResponseObject(customer));
}
UPD. I see question Infinite Recursion with Jackson JSON and Hibernate JPA issue. But it's other question. I talk about difference in use List and Set. I am not interesting in #JsonIgnore and I don't ask about it (and I use it in my code). I want to understand why I have an error when I use Set and don't have error with List
I have two tables...a loan table and a customer table. A customer can make multiple loans but I would like to restrict the customer to one active loan at a time. They cannot create a second loan until the first loan is finished (loan.active=false)
I have set up my loan table like this :
#Entity
public class Loan implements Serializable {
private static final long serialVersionUID = 0x62B6DA99AA12AAA8L;
#Column #GeneratedValue(strategy = GenerationType.AUTO) #Id private Integer id;
#OneToOne(fetch = FetchType.LAZY)
private Customer customer;
#Column private String dateLoaned;
#Column private String dateToReturn;
#Column private String dateOfReturn;
#Column private Boolean active=false;
And the customer table like this :
#Entity
public class Customer implements Serializable {
private static final long serialVersionUID = 0x63A6DA99BC12A8A8L;
#Column #GeneratedValue(strategy = GenerationType.AUTO) #Id private Integer id;
#Column private String firstname;
#Column private String surname;
#Column private String address;
#Column private String town;
#Column private String postcode;
#Column (unique=true) private String personalnumber;
#Column (unique=true) private String emailaddress;
#OneToOne(fetch = FetchType.EAGER)
private Loan loan;
This allows me to create a new loan with the same customer. So far so good.
I would like to make a query that allows me to find if a customer already has an active loan.
My loan repository so far is :
#Query("select loan_id from Loan l where l.customer.id = :customerId and l.active = true")
Boolean customerHasActiveLoan(#Param("customerId") Integer customerId);
Is this the correct way to do this?
In spring-data-jpa you can both have #Query or write a method that generates a query. There is nothing wrong to have #Query but because your repository method is quite simple you can use also method name only
For the example the equivalent of:
//Will return the active loan, if exists, or null
#Query("select l from Loan l where l.customer.id = :customerId and l.active = true")
public Loan getActiveLoad(#Param("customerId") Integer customerId)
could be simplified as
public Local findOneByCustomerIdAndActiveIsTrue(Long id)
Sometimes method name approach can generate long method name, and for this reason, if you prefer, you can use #Query annotation
How can I share a column between two FKs to the same reference table?
I have four entities: Player,Team, TeamPlayer and PlayerScore.
Now here is the use case:
Every batsman in cricket (sorry for a non-global example) playing for a specific team will be scoring when he has a partner-batsman called the runner. Now, the PlayerScore entity needs to capture this information.
So, I must ensure that both the batsman and his partner are playing for the same team. I can use this table to understand which pairs of batsman have been the performing the best. In exact terms, I need two references from PlayerScore Entity to the TeamPlayer entity. Both of them share exactly one column, team. How can I achieve this?
Here are the four classes:
#Entity
#Table(name="team")
public class Team {
#Id
private int id;
#Column(name="name",length=50)
private String name;
}
#Entity
#Table(name="player")
public class Player {
#Id
private int id;
#Column(name="name",length=50)
private String name;
}
#Entity
#Table(name="team_player")
public class TeamPlayer {
#EmbeddedId
private TeamPlayerPK id;
#ManyToOne(targetEntity=Player.class)
#JoinColumn(name="player")
private Player player;
#ManyToOne(targetEntity=Team.class)
#JoinColumn(name="team")
private Team team;
#Column(name="name",length=50)
private String name;
#Embeddable
public static class TeamPlayerPK implements Serializable
{
private static final long serialVersionUID = 1L;
private int team;
private int player;
}
}
#Entity
#Table(name="player_score")
public class PlayerScore {
#Id
private int scoreId;
#ManyToOne(targetEntity=TeamPlayer.class)
#JoinColumns(value={#JoinColumn(name="team",referencedColumnName="team"),#JoinColumn(name="batsmen",referencedColumnName="player")})
private TeamPlayer batsman;
#ManyToOne(targetEntity=TeamPlayer.class)
#JoinColumns(value={#JoinColumn(name="team",referencedColumnName="team"),#JoinColumn(name="runner",referencedColumnName="player")})
private TeamPlayer runner;
private int score;
#Temporal(TemporalType.DATE)
private Date matchDate;
}
EDIT 1: Added the Mysql WB model as suggested in the comment
EDIT 2: First unsuccessful attempt:
The Team, and Player entities remain as above. But the TeamPlayer has been changed as follows:
#ManyToOne(targetEntity=Player.class)
#PrimaryKeyJoinColumn(name="player",referencedColumnName="id")
private Player player;
The #JoinColumn has been changed to #PrimaryKeyJoinColumn
The annotations for runner field in the PlayerScore entity is changed as follows:
#ManyToOne(targetEntity=TeamPlayer.class)
#JoinColumns(value={#JoinColumn(name="team",referencedColumnName="team",insertable=false,updatable=false),#JoinColumn(name="runner",referencedColumnName="player",insertable=true,updatable=true)})
private TeamPlayer runner;
The expectation is that the FK reference for runner is also generated. THe code compiles and Eclipselink goes thru the generation but the foreign key for runner is NOT generated. In search of success yet...
I have the following two entities (Contact and Participation, linked by a ManyToMany relation) :
#Entity
public class Contact {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
#Column(nullable=false)
private String firstName;
#Column(nullable=false)
private String lastName;
#ManyToOne
private Company company;
#ManyToMany(fetch=FetchType.EAGER)
private List<Participation> participations;
}
#Entity
public class Participation {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
#ManyToOne
private Company company;
private Status status;
}
I can't figure out how to get Contacts who have a specific Participation in their list. Should I look via Contacts with a specific JPA repository method (findBy...) ? Or would i have to look via the table which was created with both Contact and Participation IDs (ManyToMany) ?
Thanks!
I am trying to migrate a Seam 2 app to CDI and use PicketLink for security. After all the reading and researching, it seems like all the examples are having one to one mapping between PicketLink model and the backend entity. e.g. Account to AccountEntity, Partition to PartitionEntity. Since I already have entities in place representing identity model, I am stuck on trying to map them to PicketLink. Here is what I have:
#MappedSuperClass
public class ModelEntityBase implement Serializable {
#Id #Generated
Long id;
Date creationDate;
}
#Entity
public Account extends ModelEntityBase {
String username;
String passwordHash;
#OneToOne(mappedBy = "account")
Person person;
}
#Entity
public Person extends ModelEntityBase {
String name;
String email;
#OneToOne
#JoinColumn(name = "account_id")
Account account;
}
Two entities (plus a super class) representing a single identity model in PicketLink, e.g. stereo type User.
Based on this why IdentityType id is String not Long, I tried to add a new Entity in:
#Entity
#IdentityManaged(BaseIdentityType.class);
public class IdentityTypeEntity implement Serializble {
#Id #Identifier
private String id;
#OneToOne(optional = false, mappedBy = "identityType")
#OwnerReference
private Account account;
#IdentityClass
private String typeName;
#ManyToOne #OwnerReference
private PartitionEntity partition;
}
I've tried a few different ways with the annotation and model classes. But when using IdentityManager.add(myUserModel), I just can't get it to populate all the entities. Is this even possible?
Got help from Pedro (PicketLink Dev). Post the answer here to help others.
This is the model class I ended up using.
#IdentityStereotype(USER)
public class User extends AbstractAttributedType implements Account {
#AttributeProperty
private Account accountEntity;
#AttributeProperty
#StereotypeProperty(IDENTITY_USER_NAME)
#Unique
private String username;
#AttributeProperty
private boolean enabled;
#AttributeProperty
private Date createdDate;
#AttributeProperty
private Date expiryDate;
#AttributeProperty
private Partition partition;
// getter and setter omitted
}
And created a new entity to map to this model:
public class IdentityTypeEntity implements Serializable {
#Id
#Identifier
private String id;
#OneToOne(optional = false, mappedBy = "identityType",
cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#AttributeValue
// #NotNull
private HAccount accountEntity;
#IdentityClass
private String typeName;
#ManyToOne
#OwnerReference
private PartitionEntity partition;
#AttributeValue
private String username;
#AttributeValue
// #Transient
private boolean enabled;
#AttributeValue
private Date createdDate;
#AttributeValue
private Date expiryDate;
}
PL can map property with #AttributeProperty to entity property with #AttributeValue. But it can only map to one entity. Therefore there is no way to map, say User and its properties over to Account and Person. But you can have the entity (in my case accountEntity) in the model. I also have to duplicate a few fields in the new IdentityTypeEntity and my existing Account entity (username, eanbled, createdDate) because PL requires these. Use a #PrePersist and similar to sync them.