Suppose we have entity A that contains a list of entities with type B (with lazy initialization).
Entity B has one BLOB field and some other, that doesn't contain much data.
How can I, using hibernate criteria query, get entity A with it's fields and each A-entity with list of Bs, but every B-entity without the BLOB field ?
Also, I do not want to extract As and iterate them to get Bs. (I now, how to use 'Projections' to extract just Bs with required fields).
Here is some code sample:
A-entity:
#Entity
#Table(name = "A")
public class A implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private Long id;
#OneToMany(mappedBy = "order", fetch = FetchType.LAZY)
#Cascade(CascadeType.ALL)
private List<B> list = new LinkedList<>();
}
B-entity:
#Entity
#Table(name = "B")
public class B implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private Long id;
#Column(name = "data", nullable = false)
#Lob
private byte[] data;
#ManyToOne(targetEntity = A.class, fetch = FetchType.EAGER)
#JoinColumn(name = "A_id", nullable = false)
private A a;
}
Related
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;
I'm with some problems trying to persist an object and its items, here're my classes:
#Entity(name = "Contract")
#Table(name = "contract")
public class Contract implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(unique = true, nullable = false)
private Long id;
#OneToMany(mappedBy = "idContract", cascade = CascadeType.ALL,fetch = FetchType.EAGER)
private List<ContractItem> contractItem;
//getters & setters...
}
.
#Entity(name = "ContractItem")
#Table( name = "contract_item")
public class ContractItem implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(unique = true, nullable = false)
private Long id;
#Column(name = "id_contract")
private Long idContract;
//getters & setters...
}
I'm extending JpaRepository im my repositories and using .save(contract) to persist but every time my application only persists the contract not de items, I've already tried CascadeType.ALL, MERGE and PERSIST in which either the result is the same, or I get an exception that my idContract must not be null.
Need some help here guys, thanks in advance !
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
I have the following POJOs for my db schema.
#Entity
#Table(name = "Quotes")
public class QuoteRequest
{
public QuoteRequest(){}
#Id
#Column(name = "quote_request_id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long QuoteRequestId;
#OneToMany(mappedBy = "quoteRequest", cascade = CascadeType.ALL)
#OrderColumn(name = "accidents_id")
private Accidents[] accidents;
// Getters and setters
}
#Entity
#Table(name = "Accidents")
public class Accidents
{
public Accidents()
{
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "accidents_id")
private long AccidentId;
#Column(name = "amount", nullable = false)
private Float amount;
#ManyToOne(optional = false, cascade = CascadeType.ALL)
#JoinColumn(name = "quote_request_id", nullable = false)
private QuoteRequest quoteRequest;
// Getters and setters
}
Because I'm using an array to store Accidents[] Hibernate is requiring me to add #OrderColumn. Adding this causes an update to be generated after insert that zeros out my accidents_id. The only way I found around that is to change Accidents[] to Set.
How can I keep Accidentsas an array and not have Hibernate force this 2nd update after the insert?
I have a performance issue with the following Hibernate TypedQuery:
select generatedAlias0 from MyClass1 as generatedAlias0
where generatedAlias0.class2.uid in (:param0, ..., :paramN)
Following the actual implementation this results in the following query:
select myclass1_.id, myclass1_.other, ... # 16 fields in total, no special big ones
from myschema.dbo.TblMyClass1 myclass1_ cross join myschema.dbo.TblMyClass2 myclass2_
where myclass1_.myclass2Id=myclass2.Id and (myclass2_.uid in('value1', ... 'valueN'))
Where N each time stands for 384 items.
When I execute this query in Toad it only takes about 150ms, but executed from code it takes almost a minute!
Class mappings
#Entity
#Table(name = "TblMyClass1", catalog = "myschema", schema = "dbo")
public class MyClass1 implements Serializable {
private static final long serialVersionUID = 8208493383744288872L;
#Id
#Column(name = "Id")
#GeneratedValue(strategy = GenerationType.AUTO)
protected Integer id;
#NotNull
#ManyToOne
#JoinColumn(name = "myclass2Id", referencedColumnName = "Id", nullable = false)
private MyClass2 class2 = null;
#NotNull
#ManyToOne
#JoinColumn(name = "myclass3Id", referencedColumnName = "Id", nullable = false)
private MyClass3 class3 = null;
#NotNull
#ManyToOne
#JoinColumn(name = "myClass4Id", referencedColumnName = "Id", nullable = false)
private MyClass4 myClass4;
#ManyToOne
#JoinColumn(name = "myClass5Uid", referencedColumnName = "UID", nullable = true)
private MyClass5 resultType;
#Column(name = "string2", nullable = true)
private String string2;
// other column fields and getters and setters ...
}
#Entity
#Table(name = "TblMyClass2", schema = "myschema", catalog = "dbo")
public final class MyCLass2 implements Serializable {
private static final long serialVersionUID = 4660579327140751989L;
#Id
#Column(name = "Id")
#GeneratedValue(strategy = GenerationType.AUTO)
protected Integer id;
#Column(name = "uid", nullable = false, updatable = false, unique = true)
private String uid;
// ... other columns fields and getters and setters
}
I only provided the mappings for the two classes in the slow query, since the follow-up queries of hibernate which fill all other linked entities all perform very good.
Using Java VisualVm I find that the following method takes 99% of the time:
com.microsoft.sqlserver.jdbc.TDSChannel.read()
I am running SQL Server 2008 and using sqljdbc4-2.0 and hibernate4.2.1 with spring3.2.9 (for transaction management)
Any help would be greatly appreciated !