I am new with gcloud DataStore Key. I was wondering how I can define my Key to use UUID ?
For example in the Instrument.java class below, how to make sure the Key object use UUID ?
import java.util.Objects;
import com.google.cloud.datastore.Key;
import org.springframework.cloud.gcp.data.datastore.core.mapping.Entity;
import org.springframework.data.annotation.Id;
#Entity
public class Instrument {
#Id
Key instrumentId;
private String type;
public Instrument(String type) {
this.type = type;
}
public String getType() {
return this.type;
}
public void setType(String type) {
this.type = type;
}
}
You are specifying it right.
As defined in the documentation, A data class must have one and only one field dedicated to storing the primary key of the corresponding datastore entity. So, the key is the UUID of the Datastore Entity.
In this case, since you are using the Spring framework org.springframework.cloud.gcp, to define the which attribute is the key, you have to specify it in the way specified in the Datastore Spring framework documentation is to use #Id.
import org.springframework.cloud.gcp.data.datastore.core.mapping.Entity;
import org.springframework.data.annotation.Id;
#Entity
public class Singer {
#Id
String singerId;
String name;
}
Related
I have a custom ID generator that generates an UUID string with a prefix for my entities ID, but since I'm using different prefix for each entity I'm having to create one ID generation class for each Entity, is there a way to only use one class for this?
My ID generation class is this:
import java.io.Serializable;
import java.util.UUID;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.IdentifierGenerator;
public class ProductIdGenerator implements IdentifierGenerator{
public static final String generatorName = "produtcIdGenerator";
#Override
public Serializable generate(SharedSessionContractImplementor arg0, Object arg1) throws
HibernateException {
String prefix = "PROD";
String uuid = UUID.randomUUID().toString().substring(0, 8);
return prefix + uuid;
}
}
My Entities looks like this:
#Entity
public class Product {
#Id
#GeneratedValue(generator = ProductIdGenerator.generatorName)
#GenericGenerator(name = ProductIdGenerator.generatorName, strategy = "net.ddns.mrq.util.ProductIdGenerator")
#Column(name = "product_id")
private String id;
private String name;
.
.
.
I have 8 entities and I had to create 8 classes like this for each of one them with different prefix.
Is there a way to make this more dynamic and less "time consuming"?
Is there a way to only change the prefix for each class without creating multiple id generation classes?
I can think of a couple of ways to solve this (which is basically the need for a custom IdentifierGenerator to be parameterized).
One idea involves each entity implementing an interface that can return the appropriate ID prefix for that entity type. Since the target entity is passed to the generator's generate() method, the generator could cast it to that interface and ask it for the prefix to use.
Another solution takes advantage of the fact that IdentifierGenerators can implement the org.hibernate.id.Configurable interface to have configuration "injected" into them, and the #GenericGenerator annotation supports setting those as #Parameters in the annotation. That way, each usage of #GenericGenerator can dictate what prefix it wants the custom generator to use. It would look something like this (note, this is untested code):
public class ProductIdGenerator implements IdentifierGenerator, org.hibernate.id.Configurable {
public static final String GENERATOR_NAME = "produtcIdGenerator";
public static final String PREFIX_PARAM = "prefix";
private String prefix = "";
#Override
public void configure(Type type, Properties params, ServiceRegistry serviceRegistry) throws MappingException {
this.prefix = params.getProperty(PREFIX_PARAM, "");
}
#Override
public Serializable generate(SharedSessionContractImplementor session, Object entityObject) throws HibernateException {
String uuid = UUID.randomUUID().toString().substring(0, 8);
return prefix + uuid;
}
}
References to it would look like this:
#Id
#GeneratedValue(generator = ProductIdGenerator.GENERATOR_NAME)
#GenericGenerator(
name = ProductIdGenerator.GENERATOR_NAME,
strategy = "net.ddns.mrq.util.ProductIdGenerator",
parameters = {#Parameter(name = ProductIdGenerator.PREFIX_PARAM, value = "foo")})
private String id;
Personally, I find the second idea a little cleaner, but there's nothing wrong with the first that I can see. It's a matter of style.
I want to use Postgresql network data type of mac address (macaddr) in Hibernate ORM. How could I map macaddr type to a entity class property? What is the best way of doing so? I never used non standard SQL types in Hibernate
Thx
Mac address is a String. If it's a #OneToOne relationship between the mac address and its user, then you don't have to make an entity class out of simple strings, just include it as a field on whatever entity needs it, like so:
private String macAddress;
If the same mac address is used by multiple entities and you want to reuse the value (normalize), then you'd make an entity like this:
package com.acme.model;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Entity
public class MacAddress implements Serializable {
private static final long serialVersionUID = 1l;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String value;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
I just solve a problem like this,so I insert and get row from DB postgresql 9 successfully. The solution explained completely is in this link network postgres types on hibernate
Because of the mac-address is never totaly validated, there is no Standard-Type in Java. You can use
#ColumnTransformer(read="CAST(mac AS varchar)", write="CAST(? AS macaddr)") String
instead to read/write it as String.
I use hibernate sequences to generate id of an entity. I use PostgreSQL 9.1.
Is it possible to get entity id before it is saved to database? How?
You explicitely create a separate sequence, get its value, then insert an object with id based on that value. You will have more code, but the ID will be available before the insertion and the guarantees for sequences are exactly the same as for serially given IDs, because they are essentially the same.
In other words:
create your own sequence
make a primary key a simple int not serial
get a number from sequence
use it as an ID for your object
This question has an answer saying how to get next sequence value.
save() method returns the id of the entity that is saved. You can use it!
reference:-> http://docs.jboss.org/hibernate/annotations/3.5/api/org/hibernate/Session.html
You can implement the interface org.hibernate.id.IdentifierGenerator and create a Id generator.
Example:
import com.fasterxml.uuid.Generators;
import com.fasterxml.uuid.impl.TimeBasedGenerator;
public class TimeBasedIDGenerator implements IdentifierGenerator {
private static TimeBasedGenerator generator = Generators.timeBasedGenerator();
private static TimeBasedIDGenerator SINGLETON = new TimeBasedIDGenerator();
public static UUID generate() {
return SINGLETON.generateUUID();
}
#Override
public Serializable generate(SessionImplementor session, Object parent) throws HibernateException {
return generator.generate();;
}
}
This can be used in your Entities like this. So the id is generated by the constructor:
#Entity
public EntityClassName {
private UUID uuid;
private Integer mandatoryField;
public EntityClassName() {
}
public EntityClassName(Integer mandatoryField) {
this.uuid = TimeBasedIDGenerator.generate();
this.mandatoryField = mandatoryField;
}
#Id
#Column(name = COLUMN_XXX_UUID)
#Type(type = "java.util.UUID")
public UUID getUuid() {
return uuid;
}
// setter + other properties
}
If we make a column Id which corresponds to id of User, then why don't we put it near the variable id instead of the getter for id ? I got the answer to that here - Where to put hibernate annotations?.
But, because my book put it near the getter, it looks like some class will need to access this object via getter to serialize/persist it to a database. What is this class and how is does it perform the persistence ? Do I call its methods to do the persistence ?
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
#Entity
public class User {
private Long id;
private String password;
#Id
#GeneratedValue
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
Hibernate will use reflection to find the appropriate methods or fields on your class to read. This is why Hibernate is able to read private fields.
The code that does this reflection is called from session.save(Object object).
I still learning about Ebean ORM with Play Framework. have problem with unexpected evolution script that generated by Play!Framework. I'm using Play!Framework 2.1.1 with JDK 1.7 update 5 64-bit. Sorry, for long code snippet in this question.
I have two Ebean Model looks like following:
Course.java
package models;
import play.data.validation.Constraints;
import play.db.ebean.Model;
import javax.persistence.*;
#Entity
#Table(name = "castillo_courses")
public class Course extends Model {
public enum CourseType {
COMPULSORY(1), BASIC_INTEREST(2), ADVANCED_INTEREST(3), THESIS(4);
private int value;
CourseType(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
#Id
private String code;
#Constraints.Required
private String course_name;
#Constraints.Required
private String credits;
#Constraints.Required
private CourseType course_type;
// Ebean finder and Other getter and setter method
......
}
CourseInterest.java
package models;
import play.data.validation.Constraints;
import play.db.ebean.Model;
import javax.persistence.*;
#Entity
#Table(name = "castillo_course_interest")
public class CourseInterest extends Model {
public enum InterestType {
ARCHITECTURAL_INFRA(1), SOFTWARE_TECH(2), INFORMATION_PROCESSING(3), ENTERPRISE_SYSTEM(4), COMP_INTELLIGENCE(5);
private int value;
InterestType(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
#Id
#ManyToOne
#JoinColumn(name = "course_code", referencedColumnName = "code")
private Course course;
#Id
#Constraints.Required
private InterestType interest_type;
// Ebean finder and Other getter and setter method
......
}
This is generated evolution script from the models above:
# --- Created by Ebean DDL
# To stop Ebean DDL generation, remove this comment and start using Evolutions
# --- !Ups
create table castillo_courses (
code varchar(255) not null,
course_name varchar(255),
credits varchar(255),
course_type integer,
constraint ck_castillo_courses_course_type check (course_type in (0,1,2,3)),
constraint pk_castillo_courses primary key (code))
;
create table castillo_course_interest (
course_name varchar(255),
credits varchar(255),
course_type integer,
interest_type integer not null,
constraint ck_castillo_course_interest_course_type check (course_type in (0,1,2,3)),
constraint ck_castillo_course_interest_interest_type check (interest_type in (0,1,2,3,4)))
;
create sequence castillo_courses_seq;
create sequence castillo_course_interest_seq;
# ..... !DOWNS code not shown
What I expected with the generated evolution script is:
In castillo_courses CREATE TABLE script, ck_castillo_courses_course_type constraint should check in (1,2,3,4) as defined by CourseType.value attribute, not to check in (0,1,2,3). I suspect evolution generated this check by using ORDINAL value of my Enums.
In castillo_course_interest CREATE TABLE script, it define again all castillo_courses fields except code. I expect the script is only define course_code column as defined by #JoinColumn annotation. There is another problem here. It has no script to generate primary key constraint too, because I have defined two #Id defined in model.
I appreciate to anyone that can explain, give advice, or help me with this problem.. :)
Kindly regards.
user the #EnumValue("1")
sample.
If all the values are parsable as Integers then Ebean will persist and fetch them as integers rather than strings.
public enum InterestType {
#EnumValue("1")
ARCHITECTURAL_INFRA(1),
#EnumValue("2")
SOFTWARE_TECH(2),
#EnumValue("3")
INFORMATION_PROCESSING(3),
#EnumValue("4")
ENTERPRISE_SYSTEM(4),
#EnumValue("5")
COMP_INTELLIGENCE(5);
private int value;
InterestType(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
For question number 1, I used suggestion from #publiclass1.
For question number 2, I learn about Compound Primary Key. On CourseInterest model, I used the Compound Primary Key because I want it to have 2 type of primary key, one is the foreign key (course_code) and the other is a common field (interest_type). So, I tried like following.
This is sample of CourseInterest model :
#EmbeddedId // using compound primarykey
public CourseInterestPK key;
#MapsId("courseCode") // map embedded key
#ManyToOne
#JoinColumn(name = "course_code", referencedColumnName = "code")
public Course course;
#MapsId("interestType") // map embedded key
#Constraints.Required
public InterestType interest_type;
This is sample of CourseInterestPK (Compound Primary Key definition) class:
#Embeddable
public class CourseInterest15541120PK {
#Column(name = "course_code")
public String courseCode;
#Column(name = "interest_type")
public CourseInterest.InterestType interestType;
#Override
public boolean equals(Object obj) {
... // MUST to override this method
}
#Override
public int hashCode() {
... // MUST to override this method
}
}
So, with these technique, I get the evolution script that I want to. ;)