I recently upgraded from hibernate-core 4.1.7 to 5.0.9 and Have problem with this code:
#ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH})
#JoinColumn(name = "FK_AAA", foreignKey = #ForeignKey(name = "CS_BBB"))
#org.hibernate.annotations.Index(name = "IDX_CCC", columnNames = "FK_DDD")
private ImportData importData;
This generate correct foreign columns pointing to the defining class, but also generating a column on the same class:
IMPORTDATA RAW(255)
Why is this raw(255) column generated ? I think it was not generated with Hibernate-core 4.1.7
any idea ?
Update 1: here is longer code fragments:
#MappedSuperclass
#Access(AccessType.PROPERTY)
public abstract class BaseEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
public abstract Long getId();
}
#Entity
#Table(name = "IMPORT_DATA", uniqueConstraints = {
#UniqueConstraint(name = "UC_IMP_BID", columnNames = {"BUSINESS_ID"})
}, indexes = {
#Index(name = "IDX_IMP_DGXML_ID", columnList = "FK_DGXML_ID"),
#Index(name = "IDX_IMP_IMPXML_ID", columnList = "FK_IMPXML_ID")
})
public class ImportData extends BaseEntity {
#Id #GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() { return id; }
// ...
}
#Entity(name = "MUTATION")
#Table(name = "MUTATION")
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name = "TYPE", discriminatorType = DiscriminatorType.STRING)
#SequenceGenerator(name = "mutationsSeq", sequenceName = "MUTATIONS_SEQUENCE", allocationSize = 1)
public abstract class Mutation extends BaseEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO, generator = "mutationsSeq")
private Long id;
#ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH})
#JoinColumn(name = "FK_IMP_ID", foreignKey = #ForeignKey(name = "CS_MUT_IMP_ID"))
#org.hibernate.annotations.Index(name = "IDX_MUT_IMP_ID", columnNames = "FK_IMP_ID")
protected ImportData importData;
}
#Entity(name="XXX")
#DiscriminatorValue("XXX_DISC")
public class XXX extends Mutation {
// ...
}
I found an answer on Mapping composite key with Hibernate produces a raw field in Oracle:
I was mixing annotations on fields and methods. I also had #Id on an abstract superclass, and a redefinition on a derived class.
Fixing theses two elements, cleaning DB and regenerating in "create" ddl mode proved that the fix was no longer generating RAW field type.
Thanks for all your helps!
Related
I am using Spring Data JPA with MS SQL. I have a table named timeseries.
Timeseries.java:
#Entity(name = "timeseries")
#Table(indexes = { #Index(columnList = "agent_id, aspect_id, _time") })
#IdClass(TimeseriesId.class)
public class Timeseries
{
#Id
#Column(name = "agent_id", nullable = false)
private String agentId;
#Id
#Column(name = "aspect_id", nullable = false)
private String aspectId;
#Id
#Column(name = "_time", nullable = false)
private Timestamp time;
#Column(name = "value", nullable = false, columnDefinition = "TEXT")
private String value;
// needed for hibernate
public Timeseries()
{
}
public Timeseries(Timestamp time, String agentId, String aspectId, String value)
{
super();
this.time = time;
this.agentId = agentId;
this.aspectId = aspectId;
this.value = value;
}
}
I did not want to keep exclusive column only for id. So I wanted to build a composite primary key.
My key will be composed of agent_id, aspect_id and _time
So here is my Id class:
public class TimeseriesId implements Serializable
{
private String agentId;
private String aspectId;
private Timestamp time;
public TimeseriesId()
{
}
public TimeseriesId(String agentId, String aspectId, Timestamp time)
{
this.agentId = agentId;
this.aspectId = aspectId;
this.time = time;
}
//... hashCode and equals methods
}
I thought giving 3 columns as primary key would make my read queries faster but now I think JPA is not using my primary key. Because it is resulting much more slower response times. Here is my repository interface.
public interface TimeseriesRepository extends JpaRepository<Timeseries, TimeseriesId>
{
List<Timeseries> findByAgentIdAndAspectIdAndTimeBetween(String agentId, String aspectId, Timestamp from,
Timestamp to);
Optional<Timeseries> findById(TimeseriesId id);
}
Here how I call in my service layer:
TimeseriesId id = new TimeseriesId(agentId, aspectId, timeStamp);
Optional<Timeseries> timeseriesOptional = timeseriesRepository.findById(id);
//... or the other one as:
List<Timeseries> timeSeriesList = timeseriesRepository.findByAgentIdAndAspectIdAndTimeBetween(agentId,
aspectId, timeStampFrom, timeStampTo);
But my problem is my query findByAgentIdAndAspectIdAndTimeBetween is not using the index. How to enforce my indexes are used in the query. I am also not sure if findById also uses an index or not. Can you please help me to ensure and enforce the usage of the indexes?
I have 3 entity classes with relations as below:
class SocietyData {
#OneToMany(mappedBy = "societyData")
private List<SubsectionData> subsectionDataList = new ArrayList<>();
}
class SubsectionData {
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "society_id", nullable = false)
private SocietyData societyData;
#OneToMany(mappedBy = "subsectionData")
private List<BasementData> basementDataList = new ArrayList<>();
}
class BasementData {
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "subsection_id", nullable = false)
private SubsectionData subsectionData;
}
I am trying to fetch society data information by using entity graph:
#Repository
public interface SocietyRepo extends JpaRepository<SocietyData, Long> {
#EntityGraph(attributePaths = {"subsectionDataList", "subsectionDataList.basementDataList"})
Optional<SocietyData> findById(long id);
}
I am not getting proper society data object and getting cant parse json exception after taking so long time sometimes!
How to solve this?
Thanks in Advance.
I am trying to use Hibernate for the first time, so I am not very familiar with the syntax yet. I am trying to model a library system. The classes that are causing problem are "Borrow" and "CopyBook" which are as following:
import javax.persistence.*;
#Entity
#Table(name = "copybook", schema="project")
public class CopyBook {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="copy_id", unique = true, nullable = false)
private int copyId;
#Convert(converter = StatusAttributeConverter.class)
#Column(name="status", columnDefinition = "TEXT DEFAULT 'AVAILABLE'")
private Status status;
#ManyToOne(optional = false)
#JoinColumn(name = "book_id")
private Book book;
public Book getBook() {
return book;
}
public void setBook(Book book) {
this.book = book;
}
#OneToOne(mappedBy = "copy")
private Borrow borrow;
public Borrow getBorrow() {
return borrow;
}
public void setBorrow(Borrow borrow) {
this.borrow = borrow;
}
#OneToOne(mappedBy = "copy", optional = false)
private Order order;
public Order getOrder() {
return order;
}
public void setOrder(Order order) {
this.order = order;
}
}
import org.hibernate.annotations.NotFound;
import org.hibernate.annotations.NotFoundAction;
import javax.persistence.*;
import java.util.Date;
#Entity
#Table(name = "borrow", schema = "project")
public class Borrow {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="no_borrow", unique = true, nullable = false)
private int noBorrow;
#Temporal(TemporalType.TIMESTAMP)
#Column(name="date_borrow", columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP", insertable = false, updatable = false, nullable = false)
private Date dateBorrow;
#Temporal(TemporalType.TIMESTAMP)
#Column(name="date_return")
private Date dateReturn;
#Temporal(TemporalType.TIMESTAMP)
#Column(name="max_date_return", insertable = false, updatable = false)
private Date maxDateReturn;
#OneToOne(optional = false)
#JoinColumn(name = "copy_id")
#NotFound(action = NotFoundAction.IGNORE)
private CopyBook copy;
public CopyBook getCopy() {
return copy;
}
public void setCopy(CopyBook copy) {
this.copy = copy;
}
#ManyToOne(optional = false)
#JoinColumn(name="mem_id")
private Members member;
public Members getMember() {
return member;
}
public void setMember(Members member) {
this.member = member;
}
}
I am using IntelliJ, so when I try to run the query of the Borrow entity it showed me that it cannot find CopyBook with id 1 even though it actually exists in the database
This is the entries currently present in my database (In these two table)
CopyBook:
Borrow:
As we can see, there is indeed a CopyBook with id of 1. This is also proved when I run the query of CopyBook entity which successfully returned all the results
Result after running in JPA select entity from CopyBook entity
Just to see what results Borrow is actually giving, I have added #NotFound(action = NotFoundAction.IGNORE). And this is the result I get
So I found this is a very bizarre situation because all data exist, and CopyBook is able to find its correspondent Borrow. But Borrow is unable to find its correspondent CopyBook ?
Strangley, I have another entity class Order which has almost the same attributes (Also has a OneToOne relationship with CopyBook), and it works perfectly.
Problem Solved.
Because I have multiple One-To-Many relationship, and the FetchType is by default Eager. Whenever I want to retrieve the entity, it will perform Left Outer Join for all the entities until the end.
However, under the scope of this context. A book does not have to be ordered to exist in the library, be performing "JOIN" it loses entries and therefore causes the aforementioned problem.
As a result, all I did was to set the attributesOrder and Borrow with optional = true and fetch = Fetchtype.Lazy so it will not perform join unless necessary
I am using spring boot data jpa with SQLServer and spatial dialect as below:
spring.jpa.properties.hibernate.dialect=org.hibernate.spatial.dialect.sqlserver.SqlServer2008SpatialDialect
Parent Class:
#Entity
#Table(name = "users", schema = "dbo")
public class User {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
#ManyToMany(cascade = {CascadeType.ALL}, fetch = FetchType.EAGER)
#JoinTable(name = "users_roles",
joinColumns = #JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(name = "role_id", referencedColumnName = "id"))
private Collection<Role> roles = new ArrayList<>();
}
Child Class:
#Entity
#Table(name = "roles", schema = "dbo")
public class Role {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
#ManyToMany(mappedBy="roles", cascade = {CascadeType.ALL})
private Collection<User> users = new ArrayList<>();
}
on saving user:
u.setRoles(roles);
userRepository.save(u);
but alyways get user_id equals zero on table users_roles
please help
Note that SpatialDialect is needed to manage spatial data on other entities.
I have a Priv class
#Entity
#Table(name = "PK_PRIVS", schema = "dbo")
public class Priv implements java.io.Serializable{
private static final long serialVersionUID = 1L;
private String code;
private String name;
private String description;
private PrivType type;
//...
}
and a Report class which has many to many relation with Priv and contains Set of associated Privs - privs.
#Entity
#Table(name = "REPORT", schema = "dbo")
public class Report implements java.io.Serializable {
//...
private Set<Priv> privs = new HashSet<Priv>(0);
//...
#JsonIgnore
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "REPORT_PK_PRIVS", schema = "dbo", joinColumns = { #JoinColumn(name = "REPORT_ID") }, inverseJoinColumns = { #JoinColumn(name = "PK_PRIVS_CODE") })
public Set<Priv> getPrivs() {
return this.privs;
}
public void setPrivs(Set<Priv> privs) {
this.privs = privs;
}
}
Now I have a Set of Strings, which are codes of Priv classes (code is Primary Key in Priv).
Set<String> privsCodesSet; //set of codes of Priv classes
I need a criterion which allow me to find that Reports, which all codes from its Priv set contains in privsCodesSet. For example if I have privsCodeSet = {"code1", "code2"}
Report with privs with codes {"code1"" should be in result, but
Report with privs with codes {"code1", "code2", "code3"} should not.
I also have class which is join of Priv and Report, but I'm not sure if it's help.
This code should work
Criteria reportPrivCriteria = currentSession()
.createCriteria( Report.class, "r");
reportPrivCriteria.createAlias("privs", "p");
reportPrivCriteria.add(Restrictions.in(p.code, privsCodeSet));
Do you have something like this on your Priv class?
private Set<Report> reports;
// ...
#ManyToMany(mappedBy="privs")
public Collection<Report> getReports() {
return reports;
}