I have the following Entity structure:
public abstract class BaseEntity {
private int _version;
public BaseEntity() {
}
#Version
#Column(name = "oplock", nullable = false)
private int getVersion() {
return _version;
}
#SuppressWarnings("unused")
private void setVersion(final int version) {
_version = version;
}
//some other code goes here....
}
the concrete Entity:
#Table(name="my_table", schema="public",
uniqueConstraints=#UniqueConstraint(columnNames={"username", "attribute"})
)
public class MyEntity extends BaseEntity implements java.io.Serializable {
private int id;
private String username;
private String attribute;
private String op;
private String value;
public MyEntity() {
}
//some code goes here ....
}
Now, I select from the database an entity of MyEntity type, lock it with entityManager.lock(myEntityInstance, LockModeType.OPTIMISTIC);, modify it, and persist modifications. The thing that I expect to get is to have oplock column's value incremented (oplock is the version column), but it is untouched.
Question: Does it behave right or am I missing something? I think the right behavior would be that the oplock's value would be incremented.
Edit: After I switched from hibernate 3.6 to hibernate 4.1, I still get the same behavior.
Finally I solved my problem:
I put only #MappedSuperclass annotation above BaseEntity class. For more details you can read here.
Related
Is it possible to use Enums as a type of a field (column) in custom JPA entities? Here is an example:
#Getter #Setter
#Entity
#Table(name = "payments")
public class PaymentEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column(name = "status")
private Integer statusId;
public PaymentStatuses getStatus() {
return PaymentStatuses.valueOf(statusId);
}
public PaymentEntity setStatus(PaymentStatuses status) {
statusId = status == null ? null : status.getId();
return this;
}
}
public enum PaymentStatuses {
CREATED(1),
COMPLETED(2),
CANCELED(3);
private Integer id;
private PaymentStatuses(Integer id) {
this.id = id;
}
public Integer getId() {
return id;
}
public static PaymentStatuses valueOf(Integer id) {
for (PaymentStatuses value : values())
if (value.getId().equals(id))
return value;
return null;
}
}
Code above works fine, but approach with statusId and getStatus setStatus looks ugly a little bit.
I wanna use PaymentStatuses as a type of the field in my entity. Like this:
#Getter #Setter
#Entity
#Table(name = "payments")
public class PaymentEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column(name = "status")
private PaymentStatuses status;
}
Tell me please, is it possible?
Using #Enumerated(EnumType.ORDINAL) will not work because the ORDINAL mode starts to 0.
So the 3 first values of the enum will be represented in DB with the 0, 1 and 2 values.
while the id field in the enum to represent it in the DB goes from 1 to 3 :
CREATED(1),
COMPLETED(2),
CANCELED(3);
Besides, this way would correlate the order of elements defined in the enum with the way to represent them in database. Which not a good thing as enum values could be added/removed in the future.
A better way to address your issue is defining a javax.persistence.AttributeConverter and using it with #Convert.
So create a AttributeConverter implementation to indicate how to convert from the DB to the enum and the enum to the DB.
Then declare a PaymentStatuses status in your entity and annotate it with #Convert by specifying the AttributeConverter implementation class.
#Getter #Setter
#Entity
#Table(name = "payments")
public class PaymentEntity {
...
#Convert(converter = PaymentStatusesConverter.class)
private PaymentStatuses status;
...
}
public class PaymentStatusesConverter implements AttributeConverter<PaymentStatuses, Integer> {
#Override
public Integer convertToDatabaseColumn(PaymentStatuses status) {
return status.getId();
}
#Override
public PaymentStatuses convertToEntityAttribute(Integer status) {
return PaymentStatuses.valueOf(status);
}
}
Yes, but when you save to the database it will persist the current index of the enum value (in your case 0 for CREATED, 1 for COMPLETED, etc.) which will give you trouble if you change the enum values. To avoid this you can use the #Enumerated annotation like:
#Getter #Setter
#Entity
#Table(name = "payments")
public class PaymentEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column(name = "status")
#Enumerated(EnumType.ORDINAL) // There is also EnumType.STRING, or you can define a custom EnumType
private PaymentStatuses status;
}
You can use #Enumerated(EnumType.STRING) if you want your data to be stored in the db like the name of the Java enum name (CREATED, COMPLETED, CANCELED)
[INTRO]
Database : Apache Derby
JPA : EclipseLink
Hey, I was looking for answer but couldn't find any so here it goes. I'm writing simple sudoku app, and the next feature which I would like to add is saving my Sudoku boards in database, and retrieve them when it's needed. Here is UML diagram of my main two classes:
SudokuBoard.uml
The structure of my two entities are as follows :
The SudokuBoard entity:
#Entity
public class SudokuBoard implements Serializable, Cloneable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private static final long serialVersionUID = 1L;
#OneToMany(cascade=CascadeType.PERSIST)
private ArrayList<SudokuField> board;
public ArrayList<SudokuField> board() {
return board;
}
public void setBoard(ArrayList<SudokuField> board) {
this.board= board;
}
public Long etId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
The SudokuField entity:
#Entity
public class SudokuField implements Serializable, Comparable<SudokuField>,
Cloneable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Transient
private static final Logger logger =
LoggerFactory.getLogger(SudokuField.class);
#Transient
private static final long serialVersionUID = 1L;
#Basic(fetch = FetchType.EAGER)
#Column(name = "Value")
private int value;
#ManyToOne
#JoinColumn(name = "board_fk", referencedColumnName = "id")
private SudokuBoard sudokuBoard;
The execution in DAO:
#Override
public void write(SudokuBoard obj, String path) throws
FileNotFoundException, IOException {
entityManager.getTransaction().begin();
entityManager.persist(obj);
entityManager.getTransaction().commit();
}
[PROBLEM]
I wonder if there is any possiblity to not use auto generated key but instead use String as PK in SudokuBoard entity. In my application I implemented binding so I would like to save the same object of SudokuBoard which is changing over time under different names.
Hope I stated my intentions clearly. Thanks for any help and tips how it could be done.
Using String as primary key is straightforward - just declare it as such and drop the #GeneratedValue annotation.
However, changing the primary key (if that's what you mean by 'saving the same object (...) under different names') is not possible. If you try to persist/merge an existing entity under a different primary key, JPA will either raise an exception or treat it as a new entity, resulting in duplicate entries in the database. Simply put, assigning id to an entity is permanent.
All in all, I'd suggest you keep an autogenerated surrogate key and declare another unique String field for the name. Conveying business information using technical fields is rarely a good idea.
I have a very simple model class.
#Entity
#Table(name="reach")
public class Reach {
#Id
#Column(name = "uid")
private Long uId;
#Column(name = "reach_30")
private Integer reach30;
... getters, setters..
}
And here is my meta model
#StaticMetamodel(Reach.class)
public class Reach_ {
public static volatile SingularAttribute<Reach, Long> uId;
public static volatile SingularAttribute<Reach, Integer> reach30;
}
And when i print following
System.out.println("==============="+(Reach_.uId));
System.out.println("==============="+(Reach_.reach30));
I get object value for uId BUT NULL for reach30. Any idea whats going on here.
Thankx
Problem was with eclipse. Needed to clean and restart computer to get it working. But not a problem with code
I have a enum of few status value
NEW, REVIEWD, PUBLISHED, PENDING, UPDATED, SPAM, DUPLICATE, IRRELEVANT, UNPUBLISHED
I don't want to use them as enumerated so created one entity for that. For convenient I want to keep a column in entity to initialize status from enum and convert that enumerated value to a Object of status entity. for this..
I have two entity. I want to refer a column with value from another entity.
Basically I want to initialize a object with formula.
Entities are
#Entity
#Table(name = "event_status")
public class EventStatus {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="eventStatusId")
private Integer eventStatusId;
#Enumerated(EnumType.STRING)
#Column(unique = true,name="eventStatusType")
private EventStatusType eventStatusType;
public EventStatus() {
this(EventStatusType.NEW);
}
public EventStatus(EventStatusType eventStatusType) {
super();
this.eventStatusType = eventStatusType;
}
public Integer getEventStatusId() {
return eventStatusId;
}
public EventStatusType getEventStatusType() {
return eventStatusType;
}
public void setEventStatusId(Integer eventStatusId) {
this.eventStatusId = eventStatusId;
}
public void setEventStatusType(EventStatusType eventStatusType) {
this.eventStatusType = eventStatusType;
}
}
I have another entity in which I am referring object of this entity
#Entity
#Table(name = "event_")
#Inheritance(strategy = InheritanceType.JOINED)
public abstract class Event implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "id_")
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Transient
public EventStatusType eventStatusType = EventStatusType.NEW;
#ManyToOne(fetch = FetchType.EAGER, targetEntity = EventStatus.class)
#Formula("select * from event_status where eventStatusId= 1")
private EventStatus status;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public EventStatus getStatus() {
System.out.println("Event.getStatus() " + status);
return status;
}
public void setStatus(EventStatus status) {
System.out.println("Event.setStatus()");
this.status = status;
}
}
This is not giving any exception but not initializing this value.
Is it possible to initialize this EntityStatus with value of eventStatusType in Event entity
I would like to explain that based on the documentation:
5.1.4.1.5. Formula
Sometimes, you want the Database to do some computation for you rather than in the JVM, you might also create some kind of virtual column. You can use a SQL fragment (aka formula) instead of mapping a property into a column. This kind of property is read only (its value is calculated by your formula fragment).
#Formula("obj_length * obj_height * obj_width")
public long getObjectVolume()
The SQL fragment can be as complex as you want and even include subselects.
...
5.1.7.1. Using a foreign key or an association table
...
Note
You can use a SQL fragment to simulate a physical join column using the #JoinColumnOrFormula / #JoinColumnOrformulas annotations (just like you can use a SQL fragment to simulate a property column via the #Formula annotation).
#Entity
public class Ticket implements Serializable {
#ManyToOne
#JoinColumnOrFormula(formula="(firstname + ' ' + lastname)")
public Person getOwner() {
return person;
}
...
}
Also, we should use insertable = false, updatable = false, because such mapping is not editable
I'm trying to use an #Embeddable inside annother #Embeddable, which is supported according to the specs, however, it looks as though the JPA annotation in de Code class below is ignored. The enum is (de)serialized by ordinal instead of string representation. I can think of several workarounds, but that's not the issue. I'm trying to understand what I'm doing wrong.
I'm using hibernate 4.2.5 with Spring 3.2.4
#Entity
public class ExampleEntity implements Serializable {
#Id
#GeneratedValue
private Long id;
#ElementCollection(fetch = EAGER)
#CollectionTable(name="example_embeddable",
joinColumns=#JoinColumn(name="example_entity_id"))
private Set<ExampleEmbeddable> embeddables = new HashSet<>();
// This enum is (de)serialized as a string just fine
#Enumerated(EnumType.STRING)
private AnotherEnum another;
private String stuff;
}
#Embeddable
public class ExampleEmbeddable implements Serializable {
#Embedded
private Code code;
// This enum is (de)serialized as a string just fine
#Enumerated(EnumType.STRING)
private StatusEnum status;
}
#Embeddable
public class Code implements Serializable {
public enum Version {
RED,
BLUE,
GREEN
}
private String code;
//Why is this enum is (de)serialized by ordinal?
#Enumerated(EnumType.STRING)
private Version version;
}