I have the following entity class:
public class SportData {
//other attributes
#Column(name = "POINTS")
#ElementCollection
private Map<NBAEvent, Integer> points;
}
public enum NBAEvent {
THREE_POINT,
TWO_POINT,
FREE_THROW,
//..
}
When I generate the corresponding tables using ddl-auto: validate it creates the NBAEvent(which is the k) column with the data type as an integer(points_key int4 NOT NULL).
How can I generate a varchar type column for the points key column?
If I manually write the SQL like points_key CHARACTER VARYING(255) how would it affect?
I'm using Spring boot along with Spring JPA, DB is PostgreSQL.
When the key of your Map is an enum then you must also add the MapKeyEnumerated annotation.
The key is to declare it with the EnumType.STRING type.
#ElementCollection
#CollectionTable(name = "colltable")
#MapKeyEnumerated(EnumType.STRING)
#Column(name="POINTS")
private Map<NBAEvent, Integer> map;
Otherwise as per javadocs it defaults to: javax.persistence.EnumType.ORDINAL. And that results in an integer table while ddl creation.
you may also need the #CollectionTable annotation as above.
Related
This question is about ordering inside a composed index, which is a more specific problem than ordering columns inside a table.
I have a simple class with a composed id:
#Embeddable
class PrimaryKeyClass {
private int a;
private int b;
}
#Entity
class SimpleClassWithComposedId {
#EmbeddedId
PrimaryKeyClass id;
}
It seems like hibernate is generating the primary key with the fields ordered by lexicographical order, at least it was what happened in my tests cases. But i would like to know if there is a way to specify the order of the fields in the primary key, because this is very important since we can heavily optmize queries that use a prefix of the composed index ( i have read this in the postgres docs )
One option would be to rename the columns in the table in the lexical order.
Alternatively, does adding a Column name help?
#Column(name = "a")
private int k_2a;
#Column(name = "b")
private int k_1a;
I have two entities call them A and B. There is a relationship entity C that supports a many-to-many relationship between A and B. C has a foreign key to A and a foreign key to B both marked with a #ManyToOne and #JoinColumn annotation.
My user wants the system to enforce that only one C record can be created for a given A and B so I'd like to declare that the combination of the A foreign key and the B foreign key must be unique.
I've tried to use the following annotation on the C table but get an error that they foreign keys listed do not exist.
#Table(uniqueConstraints=#UniqueConstraint(name = "UIDX_a_b", columnNames = {"aId, bId"}))
#Entity
#Table(uniqueConstraints=#UniqueConstraint(name = "UIDX_a_b", columnNames = {"aId, bId"}))
public class C{
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
#ManyToOne(optional=false)
#JoinColumn(name="aId")
private A a;
#ManyToOne(optional=false)
#JoinColumn(name="bId")
private B b;
...
When I tried to #Table annotation, I get the following error:
Caused by: org.hibernate.AnnotationException: Unable to create unique key constraint (aId, bId) on table C: database column 'aId, bId' not found. Make sure that you use the correct column name which depends on the naming strategy in use (it may not be the same as the property name in the entity, especially for relational types)
columnNames = {"aId, bId"} should probably be columnNames = {"aId","bId"}
Or if that's not producing quite the structure you're looking for, perhaps this variant
#Table(indexes = { #Index(name = "UIDX_a_b", columnList="aId,bId", unique = true) })
I need to do a report that says which fields has been changed of a specific table. So I found this attribute on Envers to identify those fields: withModifiedFlag=true. I known that I can do just for the fields that I want or for the whole table.
Do I have to set each field of my entity with the modifiedColumnName or there is a default name for those columns?
I tried to create a column field_name_modified with type boolean and with integer, but it didn't work. Maybe I missed something.
If we assume the following entity example
#Entity
#Audited(withModifiedFlag = true)
public class SomeEntity {
private String customerName;
}
Hibernate Envers will use the name of the field / property to determine the prefix portion of the modified column name and then append the default suffix value _MOD.
That means for the example entity above, the modified column name is customerName_MOD.
You can specify your own modifiedColumnName value, which will still have the suffix appended, but using that attribute is typically unnecessary if you wish to use the default behavior.
#Entity
#Audited(withModifiedFlag = true)
public class SomeEntity {
#Audited(modifiedColumnName = "CUSTOMER_NAME")
private String customerName;
}
The above example would use CUSTOMER_NAME_MOD.
The data-type used should whatever your dialect uses for boolean values.
I have a table with three fields, say a, b, c. I would like to add a constraint ensuring that if a is not null, then also b and c are not null. I have done that using following SQL
ALTER TABLE sample
ADD CONSTRAINT no_nulls
CHECK (CASE WHEN a IS NOT NULL THEN b IS NOT NULL AND c IS NOT NULL END)
Is there a way to achieve same effect using hibernate annotation #Check?
I can't find a helpful example with that annotation, do developers tend not to use it at all?
Yes it is possible if #Check is used at class level like this:
#Entity
#Check(constraints = "COL_A IS NULL OR (COL_B IS NOT NULL and COL_C IS NOT NULL)")
public class Sample {
#Column(name = "COL_A")
private Long a;
#Column(name = "COL_B")
private Long b;
#Column(name = "COL_C")
private Long c;
}
(Note that I rewrote your condition using #jarlh comment.). The constraints clause of #Check annotation needs to refer to the name attribute of #Column (it must be pure SQL).
#Check annotation needs to be at class level because of a Hibernate bug.
Use next annotation at Class level to check all three columns, e.g.:
#Check(constraints = "COL_A >= 15 AND COL_B < 200 AND COL_C > 100")
being COL_A, COL_B and COL_C the column names to be checked
Do not check nullable columns. #NotNull is preferred over #Check.
When we have a class:
#Entity
Order implements Serializable {
#Id
private Integer id;
...
}
and:
#Entity
OrderLine implements Serializable {
#Id
private Integer id;
#ManyToOne
Order order;
...
}
What row name will the property order map to?
order_id, ORDER_ID or Order_id?
(ommiting the #JoinColumn(name='order_id') is deliberate)
I might not understand your question. However, don't you need something like below?
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="order_id", nullable=false)
Order order;
here are some examples
Here is what the JPA 1.0 specification writes about the JoinColumn annotation:
9.1.6 JoinColumn Annotation
...
The name annotation element defines
the name of the foreign key column.
The remaining annotation elements
(other than referencedColumnName)
refer to this column and have the same
semantics as for the Column
annotation.
If there is a single join column, and
if the name annotation member is
missing, the join column name is
formed as the concatenation of the
following: the name of the referencing
relationship property or field of the
referencing entity; "_"; the name of
the referenced primary key column. If
there is no such referencing
relationship property or field in the
entity (i.e., a join table is used),
the join column name is formed as the
concatenation of the following: the
name of the entity; "_"; the name of
the referenced primary key column.
...
So in your example, the default name of the foreign key column would be order_id.
References
JPA 1.0 specification
Section 9.1.6 "JoinColumn Annotation"