Is it possible to create a table that has no 'id'? For example, this is my domain:
class SnbrActVector {
int nid
String term
double weight
static mapping = {
version false
id generator: 'identity'
}
static constraints = {
}
}
When I run this SQL statement, it fails:
insert into snbr_act_vector values (5, 'term', 0.5)
I checked the table and 'id' is already set to autoincrement. I'm thinking that another option is to remove the 'id' itself. Or is there another workaround for this? Please assume that it is not an option to change the givent SQL statement.
Gorm requires an id field to work. You can fake an assigned id by using a transient variable like below. The getters and setters map the nid field to the id field.
When saving a domain object using this method you have to do:
snbrActVectgor.save(insert:true)
because grails thinks a non-null id is a persistent instance.
class SnbrActVector {
Integer id
// nid is the actual primary key
static transients = ['nid']
void setNid(Integer nid) {
id = nid
}
Integer getNid() {
return nid
}
static mapping = {
version false
id generator:'assigned', column:'nid', type:'integer'
}
}
You probably need to specify that nid is your id column.
static mapping = {
version false
id generator: 'identity', column: 'nid'
}
There is no way to have no "id". what you can do is change the name of "id" field using assigned id generator.
Try using: "id( generator: 'assigned')" instead of "id generator: 'identity'" and see if that removes the autoincrement property from the "id" database column.
Yes in Oracle you can use ROWID for ID column.
class Document {
String id
static mapping = {
table "DOCUMENTS"
version false
id column: 'ROWID'
}
}
Related
I have these tables on one DB (MySQL) which I need to sync with corresponding tables on another DB (MSSQL), but the field names are different. I was wondering what efficient way there is to convert the names of the fields after fetching the rows so that I could insert them into the other tables.
I was thinking of doing something like this. Make objects where the key is the original table column's names and the value is the destination table column's names:
{
name : UNAME
id : CID
location : LOC
}
And the rows that I fetched and need to insert would look something like this:
{
name: Ethan
id: 1234
location: somewhere1
},
{
name: Jhon
id: 5678
location: somewhere2
}
and then run on these objects and change their key names according to the conversion table, so that I can insert them to the destination table properly.
I can't just insert without field names, as the fields are not in the same order.
How can I do what I've described efficiently? Do you have ideas for better strategies to accomplish this?
thanks a lot!
Sounds about right, how about this:
const converter = {
name : UNAME
id : CID
location : LOC
}
let newData = []
dbResults.forEach(row => {
newData.push({
name: `${row[converter['name']]}`
id: `${row[converter['id']]}`
location: `${row[converter['location']]}`
})
})
EDIT:
Actually looking at the above code there is no need for the converter object:
let newData = []
dbResults.forEach(row => {
newData.push({
name: `${row['UNAME']}`
id: `${row['CID']}`
location: `${row['LOC]}`
})
})
It is possible to store json in postgres using the json data type. Check this tutorial for an introduction: http://www.postgresqltutorial.com/postgresql-json/
Consider I am storing the following json in such a field:
{
"address": {
"street1": "123 seasame st"
}
}
I want a to store separately a reference to the street field. For example, I might have another object which is using data from this json structure and wants to store a reference to where it got the data. Maybe something like this:
class Product():
__tablename__ = 'Address'
street_1 = Column(String)
data_source = ?
Now I could make data_source a string and just store namespaces like address.street, but if I did this postgres has no idea what that means. Working with that in queries would mean parsing the string and other inefficient stuff. Does postgres support referring to fields stored inside json data structures?
This question is related to JSON foreign keys in PostgreSQL , but in this case I don't necessarily want a fk relationship. I just want to create a reference, which is not necessarily enforced in the way a fk is.
update:
To be more clear, I want to reference the location of something in the json structure on another attribute and store that reference in a column. In the below code, Address.data_source is a reference to the location of the street data (for example address.street1 in this case)
class Address():
__tablename__ = 'Address'
street_1 = Column(String)
sample_id = Column(Integer, ForeignKey('DataSample.uid'))
data_source = ?
class DataSample():
__tablename__ = 'DataSample'
uid = Column(Integer, primary_key=True)
data = Column(JSONB)
body = {
"address": {
"street1": "123 seasame st"
}
}
datasample = DataSample(data=body)
address = Address(street_1=datasample.data['address']['street_1'],
sample_id=datasample.uid,
data_source=?)
As clarified, the question is seeking a way to flexibly specify a path within a JSON object of a particular record. Keys are being handled in normal columns. Constraints on JSONB fields are not available, and there is no specific support for specifying paths within JSON objects.
I worked with the following in SQL Fiddle using PostgreSQL 9.6:
CREATE TABLE datasample (
id integer PRIMARY KEY,
data jsonb
);
CREATE TABLE address (
id integer PRIMARY KEY,
street_1 text,
sample_id integer REFERENCES datasample (id),
data_source text
);
INSERT INTO datasample(id, data)
VALUES (1, '{"address":{"street_1": "123 seasame st"}}');
INSERT INTO address(id,street_1, sample_id, data_source)
VALUES (1,'123 seasame st',1,'datasample.data->''address''->>''street''');
A typical lookup of the street address (needed to retrieve street_1) would resemble:
SELECT datasample.data->'address'->>'street_1'
FROM datasample
WHERE id=1;
There is no special postgres type for identifying columns. Strings are the closest available and you will need to retrieve the string (or array of strings, or object containing strings, if one of those simplifies parsing) and use it to build the query. In tbe first code block, I stored it as the (escaped) fragment of query - 'datasample.data->''address''->>''street'''. Though longer, it would require only retrieval and unescaping to use in a new custom query. I did not find a way to use the string as a fragment within the same SQL statement, though it might be possible to combine it with other bits of text to form a full statement that could be run through EXECUTE.
I have a table which has a column named "data" of type JSONB. I am trying to come up with a SQL statement to accomoodate the recent model changes. (postgres 9.4)
"isIndiaGSTComposition" in old model needs to be changed as "auxiliaryProperties" data structure (below) in the new model.
{
"test":{
"isIndiaGSTComposition":true (boolean)
}
}
New model :
{
"test":{
"AuxiliaryProperties":[
{
"id":"indiaGSTComposition",
"booleanValue":true
}
]
}
}
Please note that, if isIndiaGSTComposition is null, it should be auxiliaryProperties : null. But if it has true or false, it needs to be in the above data structure format(like in "new model" example above).
Any help is appreciated. Thanks in advance !
You can write conversion function and use
UPDATE table
SET field = conv_func(field);
All JSON operations are here (choose your PostgreSQL version).
Use json->'test' operator to get subobject of 'test':
{
"isIndiaGSTComposition":true (boolean)
}
If you have multiple fields, you can iterate over them with
FOR _rec IN
SELECT t."key", t."value"
FROM jsonb_each(subobject) t
LOOP
...
END LOOP;
Declare new JSONB variable for new "AuxiliaryProperties" subobject and init it with '{}'::jsonb
Use jsonb_insert() to populate "AuxiliaryProperties" with "id" and "booleanValue".
Then use jsonb_insert() again to insert new subobject with key "AuxiliaryProperties" and use #- operator to delete old subobject.
I'm designing a Spring Boot REST API that will be backed by MySQL. It has occurred to me that I want, effectively, two separate models for all my domain objects:
Model 1: Used between the outside world (REST clients) and my Spring REST controllers; and
Model 2: The entities used internally between by Spring Boot app and the MySQL database
For instance I might have a contacts table for holding personal/contact info:
CREATE TABLE contacts (
contact_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
contact_ref_id VARCHAR(36) NOT NULL,
contact_first_name VARCHAR(100) NOT NULL,
...many more fields
);
and the respective Spring/JPA/Hibernate entity for it might look like:
// Groovy pseudo-code!
#Entity
class Contact {
#Id
#Column(name = "contact_id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
Long id
#Column(name = "contact_ref_id")
UUID refId
#Column(name = "contact_first_name")
String firstName
// ...etc.
}
If I only had a single model paradigm, then when Jackson goes to serialize a Contact instance (perhaps fetched back from the DB) into JSON and send it back to the client, they'd see JSON that looks like:
{
"id" : 45,
"refId" : "067e6162-3b6f-4ae2-a171-2470b63dff00",
"firstName" : "smeeb",
...
}
Nothing like exposing primary keys to the outside world! Instead, I'd like the serialized JSON to omit the id field (as well as others). Another example might be a lookup/reference table like Colors:
# Perhaps has 7 different color records for ROYGBIV
CREATE TABLE colors (
color_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
color_name VARCHAR(20) NOT NULL,
color_label VARCHAR(20) NOT NULL,
color_hexcode VARCHAR(20) NOT NULL,
# other stuff here
);
If the corresponding Color entity looked like this:
#Entity
class Color {
#Id
#Column(name = "color_id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
Long id
#Column(name = "color_name")
String name
#Column(name = "color_label")
String label
#Column(name = "color_hexcode")
String hexcode
// ...etc.
}
Then with only one model it would serialize into JSON like so:
{
"id" : 958,
"name" : "Red",
"label" : "RED",
"hexcode" : "ff0000"
}
But maybe I just want it to come back as a simple string value:
{
"color" : "RED"
}
So it seems to me that I either need two separate models (and mapper classes that map between them) or I need a way to annotate my entities or configure either Spring, Jackson or maybe even Hibernate to apply certain transformations on my entities at the right time. Do these frameworks offer anything that can help me here, or am I going to have to go with two distinct domain models here?
You can actually accomplish this with just one model and I think it is the easiest way if you are just looking for hiding fields, custom formatting, simple transformation of attributes etc. Having two models require transformation from one model to another and vice-versa which is a pain. Jackson provides a lot of useful annotations which can be used to customize the output. Some of the annotations that can be useful for you are listed below
#JsonIgnore - ignore a field/attribute. You can hide your id field using this annotation.
#JsonInclude - Can be used to specify when a field should be present in output. For eg: Whether a field should be present in output if it is null
#JsonSerialize - You can specify a custom serializer for an attribute. For eg: You have an attribute 'password' and you want to output password as '****'.
#JsonFormat - You can apply a custom format to a field. This is very useful if you have date/time fields
#JsonProperty - If you want to give a different name for your field in your output. For eg: You have a field 'name' in your model and you want to display it as 'userName' in the output.
The association names sqlmetal generates have been the source of much frustration. Sometimes the association is simply the column name with "Id" taken off the end, sometimes it generates an association name based on the foreign key constraint name.
I simply cannot figure out what steps it uses to generate these names, and a recent schema change has drastically altered the association names once again, so I'd like to get a handle on this.
I have two tables which reference each other in a sort of chain. Something like this:
class In
{
int Id;
EntityRef<Out> Yields; // YieldsId => FK_Out_Source
EntitySet<Out> In_Source; // FK_In_Source
}
class Out
{
int Id;
EntityRef<In> Yields; // YieldsId => FK_In_Source
EntitySet<In> Out_Source; // FK_Out_Source
}
These were the classes prior to the schema change, where there was an extra FK field between In and Out tables. After deleting that field, sqlmetal now generates this:
class In
{
int Id;
EntityRef<Out> Yields; // YieldsId => FK_Out_Source
EntitySet<Out> Out; // FK_In_Source
}
class Out
{
int Id;
EntityRef<In> In; // YieldsId => FK_In_Source
EntitySet<In> Out_Source; // FK_Out_Source
}
The previous classes were perfectly symmetrical as they should be, but now the generated classes are completely asymmetrical. Can anyone explain this?
Since there seems to be no rhyme or reason to this, I created a command line tool that wraps sqlmetal and rewrites the association names. It's included in my open source Sasa utilities framework, and is called sasametal.