Hibernate MappedBy for Multiple columns - java

I am using Postgresql for my database and it contains a table called user and a table called friendship, which has 2 foreign keys userA_id and userB_id. I know how to use mappedBy to check for friendships based on userA_id but I am not sure how to check for userB_id. Is there a way to tell hibernate to check a user ID from user table with both of columns on friendship table?
EDIT: Here is the code I currently have.
#Entity
#Table(name = "users")
public class UserDB implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "userid", nullable=false)
public int userID; //not null
#OneToMany (targetEntity = FriendshipDB.class, mappedBy = "userA_ID", cascade = CascadeType.ALL, fetch=FetchType.EAGER)
//#OneToMany (targetEntity = FriendshipDB.class, mappedBy = "userB_ID", cascade = CascadeType.ALL, fetch=FetchType.EAGER)
public List<FriendshipDB> friends = new ArrayList<>();
}
#Entity
#Table(name = "friendships")
public class FriendshipDB implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "friendshipid", nullable = false)
private int friendshipID; //not null
#ManyToOne
#JoinColumn(name="usera_id")
private UserDB userA_ID; //not null
#ManyToOne
#JoinColumn(name = "userB_id")
private UserDB userB_ID;
}

I think this is very specific mapping but the only solution I know is to go with 2 association like this:
#OneToMany(mappedBy = "user1")
private Collection<User> usersByFirst;
#OneToMany(mappedBy = "user2")
private Collection<User> usersBySecond;

Related

JPA/Hibernate ManyToOne Association always null

I have two entities BookingLegEntity and BookingEntity which reference each other. But anytime I try to retrieve them from the database (e.g. via findByUuid), BookingLegEntity.belongsTo remains null.
Here are my entities:
#Entity
#Table(name = "BOOKING_LEG")
#SQLDelete(sql = "UPDATE BOOKING_LEG SET deleted = true WHERE id=?")
#Where(clause = "deleted=false")
public class BookingLegEntity {
#Id
#Column(name = "ID", unique = true, updatable = false)
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(name = "UUID", nullable = false)
private UUID uuid;
#ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinColumn(name = "BELONGS_TO")
private BookingEntity belongsTo;
// ..
#ManyToOne
#JoinColumn(name = "DISTRIBUTOR")
private DistributorEntity distributor;
#Column(name = "TRANSPORT_TYPE")
#Convert(converter = TripTypeEnumConverter.class)
private TripTypeEnum transportType;
// ...
}
#Entity
#Table(name="BOOKINGS")
#SQLDelete(sql = "UPDATE BOOKINGS SET deleted = true WHERE id=?")
#Where(clause = "deleted=false")
public class BookingEntity {
#Id
#Column(name="ID", unique=true, updatable = false)
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(name="BOOKING_ID")
#Convert(converter = BookingIdConverter.class)
private BookingId bookingId;
#ManyToOne
#JoinColumn(name ="BOOKED_BY")
private UserEntity bookedBy;
// ..
#OneToMany(mappedBy = "belongsTo", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Set<BookingLegEntity> bookingLegs = new HashSet<>();
// ...
}
Here is my repository:
#Repository
public interface BookingLegRepository extends JpaRepository<BookingLegEntity, Long> {
Optional<BookingLegEntity> findByUuid(UUID id);
// ...
}
The values in the database itself look correct:
What is really strange is that this has worked before (belongsTo was not null) but suddenly stopped working. Does anyone has any idea as to what we might do wrong here?
Do not use cascade = CASCADEType.ALL on your ManyToOne annotation, because removing one BookingLeg will cause a removal of all in corresponding Booking
The solution should be to use
cascade = CascadeType.DETACH,CascadeType.MERGE,CascadeType.PERSIST,CascadeType.REFRESH}) in its stead.
I would Truncate Cascade or Delete from Bookings where original_itinerary is null before i move on to using the new entities.
Sincerely hope it helps. (No hate if it doesn't pls)
Edit : i didnt see that comment by #dey, its my own. :P saw his comment after posting my ans

HIbernate ignore fetching data from OnetoMany field

I would like to ignore #OnetoMany field in my entity. fetch data need to get actual fields but don't want to fire query to dependent table. But deleting data from parent table needs deletion from dependent table
I have tried #Transient that ignores but the delete is also being ignored. Is there any other option to tell JPA not to fetch data from childs table when i call the parent entity?
#Entity
Table(name = "User")
public class UserEntity implements Serializable {
#Id
#Column(name = "id")
private int id;
#Column(name = "SERIAL", unique = true, nullable = false)
private String serial;
#OneToMany(mappedBy = "serialBySerialId", cascade = CascadeType.ALL)
private Set<UserActionEntity> userActionsById;
}
#Table(name = "user_action")
public class UserActionEntity implements Serializable {
#Id
#Column(name = "id")
private int id;
#Column(name = "action")
private String action;
#ManyToOne
#JoinColumn(name = "USER_ID", referencedColumnName = "ID", nullable = false)
private UserEntity userByUserId;
If you don't want to fire query to dependent table, you can use (fetch = FetchType.LAZY) on UserActionEntity property.
#OneToMany(mappedBy = "serialBySerialId", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set<UserActionEntity> userActionsById;

Many to many with extra column only returns one row

I have Order's which consist of a bunch of Product's and a quantity.
My Order entity:
#Entity(name = "orders") // Select * from order order by... NO!
public class Order {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#OneToMany(mappedBy = "product", cascade = ALL, orphanRemoval = true, fetch = EAGER)
private List<OrderEntity> orderEntities = new ArrayList<>();
...
The relation between orders and products is as follows:
#Entity
public class OrderEntity implements Serializable {
#Id
#ManyToOne
#JsonIgnore
private Order order;
#Id
#ManyToOne(fetch = EAGER)
private Product product;
private int quantity;
...
My product is as follows:
#Entity
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String name;
#OneToMany(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true)
private List<OrderEntity> orderEntity;
...
The problem is that when I select an order by it's id I only get one OrderEntity back even though I can see that there are several associated with the order by looking at the database table. Anyone got a clue about what I'm doing wrong?
I think you have configured the mappedBy incoretly.. the other way round actually.
So you should have it like this:
Order:
#Entity(name = "orders") // Select * from order order by... NO!
public class Order {
#OneToMany(mappedBy = "order", cascade = ALL, orphanRemoval = true, fetch = EAGER)
private List<OrderEntity> orderEntities = new ArrayList<>();
Product:
#Entity
public class Product {
#OneToMany(mappedBy = "product", cascade = CascadeType.ALL, orphanRemoval = true)
private List<OrderEntity> orderEntity;

Hibernate - Populate sub entity on insert

Ive added 2 hibernate model objects
First table
#Entity
#Table(name = "ACTIVITIES")
public class ActivityMO extends ModelBase {
#Column(name = "CA_ID", nullable = false, insertable = true,updatable = true, length = 22, precision = 0)
#Id
#GeneratedValue(strategy = GenerationType.AUTO, generator = "G1")
#SequenceGenerator(name = "G1", sequenceName = "CSM_ACTIVITIES_SEQ")
private Long id;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "activityId", cascade = {CascadeType.ALL})
#Fetch(FetchMode.JOIN)
List<ActivitiesProductsMO> relatedProducts;
...getters / setters
}
The other table is
#Entity
#Table(name = "ACTIVITIES_PRODUCTS")
public class ActivitiesProductsMO {
#Column(name = "CAP_ID")
#Id
#GeneratedValue(strategy = GenerationType.AUTO, generator = "G1")
#SequenceGenerator(name = "G1", sequenceName = "ACTIVITIES_PRODUCTS_SEQ")
private Long id;
#Column(name = "CAP_ACTIVITY_ID")
private Long activityId;
#Column(name = "CAP_PRODUCT_ID")
private Long productId;
...getters/setters
}
The point is to populate each db record for ActivitiesProductsMO.activityId with ActivityMO.id value
I.e.
If I create an activity record with id = 555
I'll get another activity_product record with activityId of 555
How can i get this to work?
Thank you!
Instead of manually trying to map the entitiy relations with long values you should use a bidirectional OneToMany relationship from ActivityMO to ActivitiesProductsMO
change ActivitiesProductsMO to:
#Entity
#Table(name = "ACTIVITIES_PRODUCTS")
public class ActivitiesProductsMO {
// cut unimportant code ...
#ManyToOne
#JoinColumn(name = "CAP_ACTIVITY_ID")
private ActivityMO activityId;
// cut unimportant code ...
}
If you then were to persist an ActivityMO that already has ActivitiesProductsMO entries in its relatedProducts List, the Cascade type should actually take care and create those products while filling out the CAP_ACTIVITY_ID database field with the right value.
Another Possible Solution:
Use a Unidirectional OneToMany:
#Entity
#Table(name = "ACTIVITIES")
public class ActivityMO extends ModelBase {
#OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.ALL})
#Fetch(FetchMode.JOIN)
#JoinColumn(name = "CAP_ACTIVITY_ID")
List<ActivitiesProductsMO> relatedProducts;
}
And remove the
private Long activityId;
from your ActivitiesProductsMO class.
This should both lead to identical database structure. But in the second case you would no longer have the "backlink" inside java from ActivitiesProductsMO to ActivityMO

jpa mapping two properties

I need CompanyUser.companyRolCompanyUsers property with OneToMany relation, completed in each query.
JPA company_usr entity:
#Entity
#Table(name = "company_usr")
public class CompanyUser extends BaseModel implements Serializable {
#Id
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(nullable = false)
private Company company;
#Id
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "usr_id", nullable = false)
private User user;
#Column(nullable = false)
private Boolean external;
#OneToMany(fetch = FetchType.EAGER)
private List<CompanyRolCompanyUser> companyRolCompanyUsers;
....
JPA companyRol_companyUsr entity:
#Entity
#Table(name = "companyRol_companyUsr")
public class CompanyRolCompanyUser extends BaseModel implements Serializable {
#Id
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumns({
#JoinColumn(name="companyuser_company_id", referencedColumnName="company_id"),
#JoinColumn(name="companyuser_usr_id", referencedColumnName="usr_id")
})
private CompanyUser companyUser;
#Id
#ManyToOne(fetch = FetchType.EAGER)
private CompanyRol companyRol;
....
How to set mappedBy in companyRolCompanyUsers property correctly?
If i get what you want to achieve i think you need something like :
#OneToMany(fetch = FetchType.EAGER, mappedBy="companyUser")
private List<CompanyRolCompanyUser> companyRolCompanyUsers;
You can have two properties for the same column like this :
#JoinColumn(name = "CGRADO_CODIGO", referencedColumnName = "CGRADO_CODIGO")
#ManyToOne
#NotFound(action=NotFoundAction.IGNORE)
private SipreGrado sipreGrado;
#Column(name = "CGRADO_CODIGO",insertable=false,updatable=false)
private String sipreGradoCodigo;
Remember if you have sometimes the entity NULL you can skip it with that annotation
#NotFound(action=NotFoundAction.IGNORE)
Also,Remember to set
insertable=false,updatable=false
for the one that you dont want to include in the insert/update queries.

Categories