I was working on checking my understanding on polymorphism with constraints. I wrote a sample code
class parent;
rand int unsigned a;
constraint a_c { a < 1000;}
function print();
$display("The randomized data is %d\n", a);
endfunction
endclass
class child extends parent;
constraint a_c { a > 50;}
endclass
module m;
child c = new();
initial begin
c.randomize();
c.print;
end
endmodule
The output was
The randomized data is 2567677
What is going wrong here?
That is a valid result that satisfies constraint a_c { a > 50;} Since you extended constraint a_c, it overrides the constraint in the base class. If you want the constraint to be additive, you need to give it a different name from the base class.
BTW, I suggest avoiding the terms parent and child when referring to OOP inheritance. Those terms imply distinct objects. Use base/super and derived/extended classes instead.
Related
When trying to use intermediary classes to model entity relationships in Room, I have run into an issue. Whilst documentation describes how to get from a one-to-many relationship, it does not describe how to insert.
I'm assuming this cannot be done automatically, therefore we need a query to insert the parent, retrieve the ID for the parent and assign it to the child's foreign key, and then insert the child.
The problem is that I am unsure where to put such a query. If I include it in my DAO, then I will have to include superflous methods for inserting the child. If I include it in my Repository, this makes testing very difficult (if not impossible).
Does anyone know how to resolve this?
I'm assuming this cannot be done automatically, therefore we need a query to insert the parent, retrieve the ID for the parent and assign it to the child's foreign key, and then insert the child.
The first assumption is correct, that is that you have to supply the id of the parent (otherwise how is to know the parent).
However the second assumption that you have to query the parent is not always the case and not so in the scenario you describe. If when inserting a parent then the id is returned if using the convenience #Insert as a Long or an array of Longs (if inserting multiple Parents).
For example, say you have :-
#Entity
data class Parent(
#PrimaryKey
var id: Long? = null,
var other: String
)
and
#Entity
data class Child(
#PrimaryKey
var id: Long? = null,
var parentId: Long,
var otherdata: String
)
and an #Dao annotated class with :-
#Insert
fun insert(parent: Parent): Long
#Insert
fun insert(child: Child): Long
Then you can use the following, without having to query the Parent:-
var lastParent = dao.insert(Parent(other = "Parent1 other data"))
dao.insert(Child(parentId = lastParent, otherdata = "Child1 other data"))
dao.insert(Child(parentId = lastParent, otherdata = "Child2 other data"))
// Insert a Child with it's Parent together
dao.insert(Child(
parentId = dao.insert(Parent(other = "Parent2 other data")),
otherdata = "Child3 other data"
))
note even if you define the id's as Int, a Long is returned when inserting.
It is incorrect to use Int for an id as SQLite stores the id as a 64bit signed integer which is to large for an Int.
However, issues would not occur until the id reached a value that is too large for an Int (32bit signed) i.e. greater than 2,147,483,647.
I am trying to query a table(wishlist_table) to see how many times a member appears in it.
The business rule I am trying to implement is that a member can have at most five items on there wishlist at any one time.
I have been told to do this as a domain constraint so i have created a function to check how many time a membersId appear in the wishlist table but i get an error when calling the from my check constraint
CREATE TABLE WishlistTest
(
WishlistId NUMERIC(6) NOT NULL PRIMARY KEY,
CONSTRAINT chk_Wishlist CHECK (sw3.wishListUpToFiveItems() >= 0 AND sw3.wishListUpToFiveItems() < 5)
);
CREATE OR REPLACE FUNCTION functionWishListUpToFiveItems
RETURN number IS
total number(1) := 0;
BEGIN
SELECT count(*) into total
FROM Member
WHERE MemberId = 1;
IF total < 5 THEN
return total;
ELSE RETURN -1;
END IF;
END;
If someone could tell me a better way of going about this or see what I am doing wrong it would be great
I would guess that your instructor wants you to
Add an integer column to the table to store the wish list position
Add a constraint that insures that the combination of member and wish list position is unique
Add a constraint that limits the wish list position to a value between 1 and 5
For alternate approaches using triggers or materialized views (with a constraint on the materialized view) and probably more discussion about how Oracle should allow some sort of assertion syntax to enforce this sort of constraint, you can look through this askTom thread.
The Situation
I've got a database table that is mapped via NHibernate (3.3.3-SP1). The application is running on .NET4.0 and the mapping is done via FluentNHibernate (1.4.0).
CREATE TABLE Movies
(id INT PRIMARY KEY,
yearPublished DATETIME NOT NULL,
name NVARCHAR(500) NOT NULL,
description NTEXT NOT NULL)
The data would be something like this:
id | yearPublished | name | description
---+---------------+------------------------+--------------------------------------------
1 | 1968 | 2001: A Space Oddyssey | An epic drama of adventure and exploration
The Problem
I'm creating new entities of this table and want to avoid adding more than one entity for the same real world thing. I know that there is Session.SaveOrUpdate and that there is also a way to make it work with composite and natural ids but that's not really what I want since my entities actually have a primary key and I really only need the composite key for making sure that no duplicates are in the DB.
var movie = new Movies
{
yearPublished = 1968,
name = "2001: A Space Oddyssey",
description = "An awesome journey to Jupiter"
};
// Behavior right now:
// Adds a new movie besides the fact that
// the movie is already in the database
// but now has two entries
session.SaveOrUpdate(movie);
Assert.IsTrue(movie.id == 2 && movie.description == "An awesome journey to Jupiter");
// What I really want is to be able to define what
// makes an object unique other than the primary key;
// in this scenario it should look for a combination
// of "yearPublished" and "name"
session.MyAwesomeSaveOrUpdate(movie);
Assert.IsTrue(movie.id == 1 && movie.description == "An epic drama of adventure and exploration");
Is this functionality in place in NHibernate (e.g. through a custom mapping) or do I have fetch the candidates from the DB and do it by hand?
Thanks!
I solve this by adding a unique constraint on the natural key fields in the database and using an exception converter to convert the SQL Server exception into one my application can handle.
public class SqlServerExceptionConverter : ISQLExceptionConverter
{
public Exception Convert(AdoExceptionContextInfo adoExceptionContextInfo)
{
var sqlException = adoExceptionContextInfo.SqlException as SqlException;
if (sqlException != null)
{
// 2601 is unique key, 2627 is unique index; same thing:
// http://blog.sqlauthority.com/2007/04/26/sql-server-difference-between-unique-index-vs-unique-constraint/
if (sqlException.Number == 2601 || sqlException.Number == 2627)
{
// my custom exception
return new UniqueKeyException(sqlException.Message, sqlException);
}
}
return adoExceptionContextInfo.SqlException;
}
}
Another approach I can think of is to query the database for a matching record before the insert but that's not foolproof because a record could be inserted between the select and your insert.
I am having two tables One is a Master table called TRANSACTION and second is record of the transaction this table is called TRANSACTION_RECORD.
TRANSACTION
CREATE TABLE `e3_transaction` (
`transactionid` bigint(20),
`transactiontype` varchar(10),
`transactionstatus` varchar(10),
PRIMARY KEY (`transactionid`)
);
TRANSACTION_RECORD
CREATE TABLE `e3_as2805msg4` (
`transectionid` bigint(20),
`messageType` int(4),
`cardAcceptorName` varchar(40),
`adNational` varchar(1000),
`adPrivate` varchar(1000),
KEY `transectionidFK` (`transectionid`),
CONSTRAINT `transectionidFK` FOREIGN KEY (`transectionid`) REFERENCES `e3_transaction` (`transactionid`)
);
It will have one to one mapping between Transaction and transaction record. It means one transaction can have only one record. I have kept this table separately for some reasons. So my class will look like this:
#Entity
#Table(name = "e3_transaction")
public class Transaction {
#Id
#GeneratedValue(generator = "assigned-by-code")
#GenericGenerator(name = "assigned-by-code", strategy = "assigned")
#Column(name = "transactionid", unique = true, nullable = false)
private Long transactionid;
#Column(name = "transactiontype", nullable = false, length = 10)
private String transactiontype;
#Column(name = "transactionstatus", nullable = false, length = 10)
private String transactionstatus;
#oneToOne
private TransactionRecord record;
}
I want to persist both objects at a same time. when I persist a TRANSACTION, TRANSACTION_RECORD should be persist in it's table. Is there any way to do this ?
You can change the table structure if you want. Only thing i need it TWO tables.
Works with
#OneToOne(cascade=CascadeType.ALL)
#MapsId
private TransactionRecord record;
TransactionRecord must have an #Id of the same type as Transaction with no value generation.
Tried with Hibernate as JPA 2.0-provider.
There are a few options to map this, but it looks like you are handling it with two separate entities. As both entities share the same primary key value, your reference mapping will need to change based on which entity you wish to have controlling the pk value generation - as it stands, the e3_transaction.transactionid field is being set by two separate mappings; the transactionid long and the TransactionRecord record reference.
If you wish to use the #MapsId as is suggested in the other answer, you will need to move your #GeneratedValue code to the TransactionRecord entity, as the JPA provider will use the value in the referenced TransactionRecord to set the transactionid attribute and the database field. This is a simple elegant solution, but you can also remove the Long transactionid attribute from Transaction and just mark the record reference with #Id (instead of #MapsId). The long transactionId value within TransactionRecord would still be used as Transaction's id for EntityManager getReference and find calls.
A different option that allows keeping the #GeneratedValue on the transactionid within Transaction is to define the #JoinColumn annotation on the record reference and specify that the field is insertable=false, updatable=false. You then need to modify the TransactionRecord so that it has a back relationship to the Transaction so that it can pull the transectionid value from the Transaction instance to use as its id. This can be accomplished by simply marking the relationship with #ID though.
I have a unique situation working with a legacy application where I have a parent/child relationship that is based on two integer values. Unfortunately, these fields are not id and parentId or something similar. The columns are ItemId and SubItemId. When these two columns equal each other, the item is assumed to be a parent. When they differ, the ItemId references the Items parent and the SubItemId is simply an identifier of which child it is.
Here is an example
ItemId = 1, SubItemId = 1: Parent Item
ItemId = 1, SubItemId = 6: Sub Item, whose parent is the Item where the id fields are (1, 1)
ItemId = 2, SubItemId = 2: Parent Item
ItemId = 2, SubItemId = 9: Sub Item, whose parent is the Item where the id fields are (2, 2)
So with this information, I have a class hierarchy set up like this:
public class Item
public property ItemId as Integer
public property SubItemId as Integer
end class
class ParentItem : Item
end class
class SubItem : Item
public property ParentItem as ParentItem
end class
So I would like to map the ParentItem property of the SubItem class to its corresponding ParentItem using NHibernate and I can't for the life of me figure out how. I was able to get NHibernate to instantiate the correct class based on a formula discriminator, and I was hoping something similar was available for many-to-one relationships.
I'm not able to change the table structure, which certainly limits my options. Also, I'm using FluentNHibernate for my mappings, so feel free to offer suggestions using its syntax.
Thanks!
Update
I created a view that added two new columns that equated to a foreign key pointing to the parent and now I'm getting an NHibernate mapping error:
Foreign key (FK163E572EF90BD69A:ItemsNHibernateView [ParentItemID, ParentrSubitemID])) must have same number of columns as the referenced primary key (ItemsNHibernateView [ItemID, SubitemID])
This is throwing me off because to me, it looks like both keys do have the same number of columns...
Ok, I figured it out based on the comment from Ben Hoffstein. I created the view as I mentioned in the update to my original question. The error was caused by an embarassingly stupid error. When I created the array to list the column names for the foreign key, I put both names in the quotes like this:
new string() {"ParentItemID, ParentSubitemID"}
instead of:
new string() {"ParentItemID", "ParentSubitemID"}
The way that NHibernate was displaying the error threw me off the scent.