[Edit: Apparently, this is only an issue for arrays and FoxyBOA's answer might direct to (or even is) the answer.]
My question relates to these software: Hibernate3+Annotation, Spring MVC, MySQL and in this example also Spring Security.
I was wondering, why collections, which are automatically associated by Hibernate contain null values for each row number of the child table (besides the elements which are correct). My Example:
I have a users and an authorities table, the primary key of the users table is username which serves as foreign key. Right now, there are 13 rows in my authorities table. When I retrieve a user from the database (MySQL InnoDB) and Hibernate automatically retrieves the user's authorities corresponding to this mapping:
#OneToMany
#JoinColumn(name = "username")
#IndexColumn(name="id") // "id" was the primary key and is used to sort the elements
public Authority[] getAuthorities() {
return authorities;
}
public void setAuthorities(Authority[] authorities) {
this.authorities = authorities;
}
... I end up with a collection "authorities" containing 14 (0-13) elements of which only four are not-null (four rows in the database table belong to that specific user, so that is correct). As far as I realize, I am using Hibernate defaults for properties like Fetchmode etc. I am getting the user like this:
Criteria criteria = getSession().createCriteria(User.class);
criteria.add(Restrictions.eq("username",username));
User user = (User) criteria.uniqueResult();
The logging information from org.hibernate.loader.loader correctly "mentions" four rows for the resultset. Still, the user created has the four correct elements plus ten null values in the Array. In my specific example, this results in this exception:
java.lang.IllegalArgumentException: Granted authority element 0 is null - GrantedAuthority[] cannot contain any null elements
The answer lies in the #IndexColumn annotation. It is using the value of id as the array index, thus the number of elements in the Array is basically going to be the value of the highest ID in the Authorities table.
see the hibernate documentation on indexed collections
try removing the annotation.
Also just as a thought; have you considered using a Set for the mapping? it isn't strictly necessary, it just a bit more common form of mapping that's all.
I can recommend you check your data. If you have a missed indexes (id column in your case), then instead of missed id you'll get null in your array.
I.e.
table authorities:
username id
bob 1
bob 3
bob 5
As a result you will have an array:
{0=null, 1=bob, 2=null, 3=bob, 4=null, 5=bob}
UPDATE:
I met the situation in two cases:
Missed key values in indexed column id at authorities table (e.g. 0,1,3,4,5 - missing value 2. Hibernate will automatically add to an array value with key 2 and value null).
Indexed values are in order, but select criteria filter part of them (e.g. your HQL similar to that "from user u join u.authorities a where a.id=2". In that case hibernate load a user, but in authorities array you will have only 3 values: 0 - null, 1 - null, 2 - authority with id 2).
Related
I am building a training platform for work. I have created the requirements for a user to be trained based on a role given to them. If that role is aligned to a document it will sit against the user. I have managed to get most of the way but am struglling on the best way to finish the where statement within mysqli.
tbldocfiles is a list of my files. I am looking at docid (could be multiple files associated to the document)
tbltrainingaccess sets the roles (driver, warehouseman, customer services) and shows which role (by id) is associated to the document in docfiles.
tblusertraining is the list of users and what role they have associated to them. (driver, warehouseman, customer services).
I am listing the documents associated to the user so have thought the following is the best way:
Look at the user and how many roles he/she is allocated
Look at the roles returned in point 1 (where function)
Identify and match the documents that have the same roles as the user (Join function)
create the list, then look at the unique values for docid. (distinct value)
Example User Bri has the driver and warehouseman role.
There are 5 documents in the db, 3 of them are associated to the driver role (docid 1,2,3) and 2 of them are associated to the warehouseman role (docid 2,4) the 5th document is associayted to customerservice.
My query should do this:
List all documents associated to the roles, that are associated to the user Bri
1
2
3
2
4
Now select unique values (using docid) from the above list:
1,2,3,4.
So my answer will be a used as a count function at the end using mysql_fetch_rows
SELECT DISTINCT tbldocfiles.docid FROM tbldocfiles LEFT JOIN tbltrainingaccess ON (tbldocfiles.docid = tbltrainingaccess.docid) where groupid='1' or groupid='9'
The above code works. but i've got myself confused.
The where statement needs to be the result of a query similar to :
select * from tblusertrainingrole where userid='1' (1 will be a variable based on page selection)
the result in this would be 1, 9 which are the groupid results.
Basically any help would be appreciated! I am sure it will be simple but have burnt myself out on this for a while and most answers in here helped with joining but not the where statement (that I could find)
Thank you in advance everyone!
You can do a select statement in the where. Since it is an or statement you can use in for the results. Please replace * with the column name for the value you need. Should look like
where groupid in (select * from tblusertrainingrole where userid = '1')
When one models resource relationships, the classic example give is for articles and comments. This becomes simple to model because:
articles can be uniquely identified: /articles/1
comments can be uniquely identified: /comments/2
their relationship can be provided as /articles/1/comments which would return only comments for that article
But how does one handle the case where the related resource only exists within the context of the parent?
For example, order and items:
order can be uniquely identified /orders/123
the items in that order only exist as /orders/123/items
and NOT as /items
In JSON-API the relationship object needs a "type" and "id" to specify the linkage:
"relationships": {
"links": {
"self": "http://example.com/orders/123/relationships/items",
"related": "http://example.com/orders/123/items"
},
"data": {
"type": <what goes here>,
"id": <what goes here>
}
}
The type and id for data would need to be relative to order number 123. Assuming, of course, that they don't get assigned a UUID or similar from a database because they are, in fact, a composite key. They exist primarily as a foreign key combination.
How does one handle that?
One option for the relation is to use type as order_item and id as a hash or something delimited string concatenation of the order's id and the item's id. (e.g. 123_abc). 123 I get from the order and abc I get from the item in the order.
Is there another way other than avoiding the need altogether to supply resource linkage?
Every resource must be uniquely identified by a combination of type and id according to JSON API specification:
Identification
Every resource object MUST contain an id member and a type member. The values of the id and type members MUST be strings.
Within a given API, each resource object’s type and id pair MUST identify a single, unique resource. (The set of URIs controlled by a server, or multiple servers acting as one, constitute an API.)
https://jsonapi.org/format/#document-resource-object-identification
Therefor you are not only requiring an ID for resource linkage but also to build any valid response including such a resource.
But there are no rules about how you generate that unique IDs per type. Combining an unique order ID with an unique item ID to get an unique ID per item in an order seems to be a fine approach if your data model doesn't include an ID.
I am trying to use a metadata JSONB column for a multi-tenant application. Every user for each tenant must have the same metadata, but the tenants have varying metadata fields.
In order to keep all user metadata in sync per tenant, when the tenant admin modifies the metadata fields I need to make sure all users have their metadata JSONB column updated with the following criteria:
If the metadata field/key already exists, the value needs to be retained
If the metadata field/key is new, the key needs to added with a null value
If there are any metadata fields/keys that are not included in the updated list, they should be deleted from the JSON object
For example, all the users for Tenant #1 have the following metadata assigned: { "EmployeeNo" : 123, "HireDate" : "2012-10-10", "Age" : 43 } and somewhere down the line the admin decides they don't care about Age, but they do want to start tracking ParkingSpace.
I need the new metadata record to retain the EmployeeNo and HireDate values, remove the Age key/value, and add the ParkingSpace key with a null value. { "EmployeeNo" : 123, "HireDate" : "2012-10-10", "ParkingSpace" : null }.
I would have thought that I could run an update query similar to the following where it returns a JSONB object where it selects the values if the key exists and a null if it doesn't:
UPDATE users SET metadata = metadata[keys: 'EmployeeNo', 'HireDate', 'ParkingSpace'] WHERE tenant_id = 1;
Obviously that won't work, but hopefully it indicates the issue?
Update: I might have misunderstood your question. Maybe you wanted something like that instead:
UPDATE users
SET metadata = (SELECT json_object_agg(n,metadata->>n) FROM unnest(ARRAY['EmployeeNo','HireDate','ParkingSpace']) AS t(n))
This solution involves creating a brand new jsonb object by extracting only the field that you want from the original metadata. The fields to be copied over are specified as an array that you can easily customize.
Original answer: I think this should do it:
UPDATE users
SET metadata = (metadata - 'Age') || '{"ParkingSpace": null}'::jsonb;
I am using the || operator which merges 2 jsonb objects into one and the - operator which removes a key/value pair.
I have models:
class Reference(models.Model):
name = models.CharField(max_length=50)
class Search(models.Model):
reference = models.ForeignKey(Reference)
update_time = models.DateTimeField(auto_now_add=True)
I have an instance of Reference and i need to get all last searches for the reference. Now i am doing it in this way:
record = Search.objects.filter(reference=reference)\
.aggregate(max_date=Max('update_time'))
if record:
update_time = record['max_date']
searches = reference.search_set.filter(update_time=self.update_time)
It is not a big deal to use 2 queries except the one but what if i need to get last searches for each reference on a page? I would have got 2x(count of references) queries and it would not be good.
I was trying to use this solution https://stackoverflow.com/a/9838438/293962 but it didn't work with filter by reference
You probably want to use the latest method.
From the docs, "Returns the latest object in the table, by date, using the field_name provided as the date field."
https://docs.djangoproject.com/en/1.8/ref/models/querysets/#latest
so your query would be
Search.objects.filter(reference=reference).latest('update_time')
I implemented a snippet from someone in gist but I don't remember the user neither have the link.
A bit of context:
I have a model named Medicion that contains the register of mensuration of a machine, machines are created in a model instance of Equipo, Medicion instances have besides of a Foreign key to Equipo, a foreign key to Odometro, this model serves as a kind of clock or metre, that's why when I want to retrieve data (measurements aka instances of Medicion model) for a certain machine, I need to indicate the clock as well, otherwise it would retrieve me a lot of messy and unreadable data.
Here is my implementation:
First I retrieve the last dates:
ult_fechas_reg = Medicion.objects.values('odometro').annotate(max_fecha=Max('fecha')).order_by()
Then I instance an Q object:
mega_statement = Q() # This works as 'AND' Sql Statement
Then looping in every date retrieved in the queryset(annotation) and establishing the Q statement:
for r in ult_fechas_reg:
mega_statement |= (Q(odometro__exact=r['odometro']) & Q(fecha=r['max_fecha']))
Finally passed this mega statement to the queryset that pursues to retrieve the last record of a model filtered by two fields:
resultados = Medicion.objects.filter(mega_query).filter(
equipo=equipo,
odometro__in=lista_odometros).order_by('odometro', 'fecha') # lista_odometros is a python list containing pks of another model, don't worry about it.
The data is from Chrome Google history file.
I want to know the meaning of columns in tables. So I find one table called visits in the history is:
CREATE TABLE visits(id INTEGER PRIMARY KEY,url INTEGER NOT NULL,visit_time INTEGER NOT NULL,from_visit INTEGER,transition INTEGER DEFAULhT 0 NOT NULL,segment_id INTEGER,is_indexed BOOLEAN)
The table's result is :
1|10|12979306250150765|0|268435457|1|0
17|14|12979306291009421|0|838860801|2|0
18|14|12979306291724492|0|805306368|0|0
19|14|12979306296042195|0|838860808|0|0
20|14|12979306296322297|0|805306368|0|0
21|14|12979306298922534|0|838860808|0|0
22|14|12979306299261896|0|805306368|0|0
23|15|12979306305614105|0|805306368|0|0
24|15|12979306310110294|0|805306368|0|1
25|16|12979306316672464|0|805306368|0|1
So, another table called urls, which is also in this history sqlite is:
CREATE TABLE "urls"(id INTEGER PRIMARY KEY,url LONGVARCHAR,title LONGVARCHAR,visit_count INTEGER DEFAULT 0 NOT NULL,typed_count INTEGER DEFAULT 0 NOT NULL,last_visit_time INTEGER NOT NULL,hidden INTEGER DEFAULT 0 NOT NULL,favicon_id INTEGER DEFAULT 0 NOT NULL)
The table's result is:
1|http://cateee.net/xxxx|Linuxxxx|0|0|0|0|0
2|http://kernel.org/|Index of xxxxxxxxx|0|0|0|0|0
3|http://repo.orxxxxxxxxxxxxx|xxx|0|0|0|0|0
4|http://stackoverflow.com/xxxx|xxxxxx|7|0|12979644275181782|0|0
5|http://stackoverflow.com/questions/xxxxxxx|linuxxxxxxxxxxxxxxxx|0|0|0|0|0
6|http://www.db-class.org/xxxxxxxxxxxxxxxx|xxxxxxx|6|0|12979306496245203|0|0
7|http://www.xxxxxxxxxxxxxxxxxxx|xxxxxxxxxxxxxxxxxx|0|0|0|0|0
8|http://www.xxxxxxxxxxxxxxxx|xxxxxxxxxxxxxxxxxxx|0|0|0|0|0
10|http://www.google.com/|PYTHON - Googlexxxxxxxxx|1|1|12979306250150765|0|0
14|http://www.facebook.com/|Facebook|6|2|12979306750272709|0|0
15|http://www.facebook.com/profile.phpxxxxxxxxx|xxxxxxxxxxxxxxx|2|0|12979306310110294|0|0
So my problem are: is the urls table's first column called url_id represents in the visits table's second column called url INTEGER, but the relationship is not clear. And what is the meaning of transition INTEGER in visits table, can I extract the time from these, I need to get useful information from these tables, and make their relationship clear.
This site had a lot of helpful information about Chrome's SQLite tables, and how to query the tables.
An example they give on that page of joining the two tables "urls" and "visits" is as follows:
SELECT urls.url, urls.title, urls.visit_count, urls.typed_count, urls.last_visit_time, urls.hidden, visits.visit_time, visits.from_visit, visits.transition
FROM urls, visits
WHERE
urls.id = visits.url
And as for the "transition" field in the visits table, this value tells you how the URL was loaded into the browser. I'll let you check out the link I gave you for more details.