HIbernate ignore fetching data from OnetoMany field - java

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;

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

How to avoid updating child tables when using save Hibernate?

I have a parent table called USER and a child table called USERDATA linked with OneToMany. When I go to use the save method, if the child record exists it is updated. I would like it not to be updated but not added. What am I doing wrong?
My classes:
#Entity
#Table(name="USER")
#IdClass(UserPK.class)
public class User implements Serializable{
private static final long serialVersionUID = 1L;
#Id
#Column(name="USERID")
private String userId;
#Id
#Column(name="USERNUMBER")
private String userNumber;
private String name;
private String surname;
#OneToMany(mappedBy = "user", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<UserData> userDatas;
#OneToMany(mappedBy = "user", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#Fetch(value = FetchMode.SUBSELECT)
private List<OtherData> otherDatas;
//getter and setter
}
UserData:
#Entity
#Table(name="USERDATA")
public class UserData implements Serializable{
private static final long serialVersionUID = 1L;
#Id
private String id;
private String City;
private String University;
#ManyToOne
#JoinColumns({
#JoinColumn(name = "USERID", referencedColumnName = "USERID"),
#JoinColumn(name = "USERNUMBER", referencedColumnName = "USERNUMBER")
})
private User user;
//getter and setter
OtherData:
#Entity
#Table(name="OTHERDATA")
public class OtherData implements Serializable{
private static final long serialVersionUID = 1L;
#Id
private String id;
private String hobby;
private String religion;
#ManyToOne
#JoinColumns({
#JoinColumn(name = "USERID", referencedColumnName = "USERID"),
#JoinColumn(name = "USERNUMBER", referencedColumnName = "USERNUMBER")
})
private User user;
//getter and setter
And my save:
session.save(obj); //obj is and User object
when I do the first insert everything is ok, when I do it again by changing the data of the primary key of user but not quelly of the primary key of userData or otherData, the data is updated. I don't want them updated.
You can not reuse the same Java object in this case. Also, changing the primary key should produce a big fat warning when flushing that object Hibernate.
If you want a new row to be inserted, you have to create a new object with new User(). Another option is to let Hibernate forget about the old object by using session.detach(user). The problem is, that Hibernate knows the object already and due to that, tries to update the existing row when you call save again.
Try setting the column like so:
#OneToMany(mappedBy = "user", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#Column(insertable = false, updatable = false)
private List<UserData> userDatas;
I haven't tested it but it should block inserts and updates via the entity. Of course you will need separate queries to insert update UserData somehow.
BTW I suggest not to use FetchType.EAGER, but always use FetchType.LAZY. If you need the child data to be fetched, just adapt the query you are using to do a FETCH JOIN, see here for an example:
SELECT FROM User u LEFT JOIN FETCH u.userData d
Hi Fesilox Please write this example
#JoinColumn(name = "USERID", referencedColumnName = "USERID", nullable = false,
insertable=false, updatable=false)

Hibernate MappedBy for Multiple columns

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;

Jpa: delete dependents instead of updating them

In my application every customer can have several accounts. I have the following data structure (a lot omitted for brevity):
#Entity
#Table(name = "CUSTOMER")
public class Customer {
#Id
#Column(length = 36, name = "CUSTOMER_ID", nullable = false, unique = true)
private String id;
#OneToMany
#JoinColumn(name = "OWNER_ID", referencedColumnName = "CUSTOMER_ID")
private List<Account> accounts;
}
#Entity
#Table(name = "ACCOUNT")
public class Account {
#Id
#Column(length = 36, name = "ACCOUNT_ID", nullable = false, unique = true)
private String id;
#Column(name = "OWNER_ID", nullable = false)
private String ownerId;
}
If I use JPA to delete a Customer, such as
entityManager.remove(customer);
it tries to update the related ACCOUNT.OWNER_ID fields with null. OWNER_ID is not nullable, so it throws a JDBCException and rolls back the transaction.
What I need to achieve is that the related ACCOUNT rows get deleted (if any). How can I do that?
Thank you
Update: I tried it with
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
but it does not change the behavior: still tries to update with null.
I think you need to be using cascading in order to remove the child elements. Try this:
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "OWNER_ID", referencedColumnName = "CUSTOMER_ID")
private List<Account> accounts;
You should also reference the Customer in your account by a ManyToOne relationship and not the String id. I think this should solve your issue:
#Column(name = "OWNER_ID", nullable = false)
#ManyToOne
private Customer owner;

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