In springJdbctemplate crud application I want to give user an option to create a new custom table with custom fields.The problem is if I create query to create table ,how can I give the user the option to customise it ,as domain class are fixed.Some one suggest to dump data in xml.
thanks
You need to have user table metadata definition in this way:
Domain classes (pseudo-code):
class UserTableMetadata {
String tableName;
// List of personalisable columns
List<UserTableColumnMetadata> columns;
// List of personalisable indexes
List<UserTableIndexMetadata> indexes;
}
class UserTableColumnMetadata {
// Owner table
UserTableMetadata table;
String columnName;
int jdbcType;
int lenght;
int precision;
boolean nullable;
}
class UserTableIndexMetadata {
// Owner table
UserTableMetadata table;
String indexName;
boolean unique;
boolean primary;
// Index columns
List<UserTableColumnMetadata> columns;
}
As you can see domain classes are fixed, but you can build up a simple table definition with Name, Columns and Indexes.
After that can be easy - processing metadata - build the create table SQL code in dynamic way (or alter table if user change column definition and table already exists).
Metadata can be stored in database as well as on XML, it's only a choice based on your preference and requirements.
Enjoy!
Related
In Grails, Gorm, I have this entity:
class MyEntity implements Serializable {
Long bankTransactionId
int version
BigDecimal someValue
static constraints = {
bankTransactionId(nullable: false)
version(nullable: true)
someValue(nullable: true)
}
}
Doing MyEntity.findByBankTransactionId(Long.valueOf("3")) throws this exception:
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown
column 'this_.id' in 'field list'
I am suspecting the fact that my column has the name id in it. Could it be this?
How to fix it then ?
Thanks.
Everything you have provided here looks fine. In particular, there are no restrictions about having the letters "id" in a column name.
Take a look at your generated MySQL table. I'm guessing that the id column isn't there for some reason. Maybe something prevented generating it due to some earlier error that you have now corrected, or you have your datasource set to "none" instead of "update" (or similar) and the whole table is missing!
If this is just a development environment with no real data (and no foreign key constraints), drop the whole MyEntity table and let it be automatically recreated. If not, move to a different temporary datasource, let a new table be created, and compare the two. If the new one still doesn't have an id column, you have something going wrong during your startup that is preventing your tables from being created correctly. You could just add the column in manually, but if you don't figure out what happened to it in the first place, it will probably just happen again.
For reference, in my test environment, my MySQL table for "MyEntity" copied from your example looks like:
desc my_entity;
'id','bigint(20)','NO','PRI',NULL,'auto_increment'
'version','int(11)','YES','',NULL,''
'bank_transaction_id','bigint(20)','NO','',NULL,''
'some_value','decimal(19,2)','YES','',NULL,''
I am trying to create mysql table using groovy domain class. I have one master table and other table with has reference to field in the master table.
Let me explain more clearly. I have a master table
QualificationMaster
`````````````````
QualificaitonID
QualificationName
QualificaitonDuration
UserQualificationMap
```````````````````
Username
Email
QualificationID (this field refers to QualificationID in QualificationMaster)
Please help me in getting this done by using groovy domain class with sample snippet...I searched a lot but I find it so confusing..please help me as i am very new to groovy and helps me a lot. I am using GGTS IDE for this.
Check this out:
class QualificationMaster{
String QualificationName
Integer QualificaitonDuration
}
class UserQualificationMap{
String Username
String Email
QualificationMaster Qualification
}
You do not have to use QualificationMaster.QualificaitonID as primary key for QualificationMaster. QualificationMaster.id is created by default for each domain class (you can check it in your db).
Therefore you can make a reference to QualificationMaster from UserQualificationMap. It will be mapped as QualificationMaster's primary key in UserQualificationMap table.
Moreover try to use shorter and lowercased names for properties in your domain classes. For example change QualificationMaster.QualificationName to QualificationMaster.name and QualificationMaster.QualificaitonDuration to QualificationMaster.duration.
I am using Entity Framework 4.2 Code First and MySQL. I need to be able to do a full text search across several fields of my table. However, I am having a number of issues with this:
1) Full text search under MySQL requires the MyISAM table type. However, when I run the DropCreateDatabaseAlways initializer, the table type I get is InnoDB. Here is an example of my table definition:
[Table("Patient")]
[Serializable]
public class Patient
{
public Patient()
{
}
[Key]
public int PatientID { get; set; }
[MaxLength(50)]
public string FirstName { get; set; }
[MaxLength(50)]
public string LastName { get; set; }
}
Is it possible to specify MyISAM table type? If so, how?
2) I need to specify the full text index:
ALTER TABLE `patient` ADD FULLTEXT INDEX `Name`(`FirstName`, `LastName`);
One possibility I can think of is:
public class MyDbInitializer : DropCreateDatabaseAlways<MyDbContext>
{
protected override void Seed(MyDbContext context)
{
context.Database.ExecuteSqlCommand(
"ALTER TABLE `patient` ADD FULLTEXT INDEX `Name`(`FirstName`, `LastName`)");
}
}
Is there a better way?
3) I need to be able to search using the full text index. Ideally in a way that works with my existing linq to SQL.
One less-then-desirable possiblity I can think of is to create a stored procedure (again, using ExecuteSqlCommand) that takes a string and returns either a list of matching PatientIDs or a list of Patient rows. For example:
IEnumerable<int> patientIDs = [...call stored proc to get matching ids...]
var patients = from p in patients
where patientIDs.Any(pid => pid == p.PatientID)
select new {...}
Or:
var patients = from p in [...call stored proc to get matching patient records...]
select new {...}
How would I do this? Is there a better way?
4) Bonus question: Even though I specify the [MaxLength(50)] attribute, my strings are being stored as MEDIUMTEXT instead of VARCHAR(50) as I would expect. Without the [MaxLength] attribute I get LONGTEXT. How do I specify VARCHAR(n) for strings types?
Any ideas?
Thanks in advance,
Dan
It is provider specific so unless your provider for MySQL offers some way to change it you will not be able to do that from code first. I think you should be able to run ALTER TABLE in custom DB initializer to change the engine.
If you use migration feature (EF 4.3 and newer) you can script the index in the migration otherwise you need to use your initializer.
You need to query the database with SQL. EF has no support for fulltext search queries. To call a stored procedure you must use SqlQuery and populate a type with same properties as the result set.
Try to use [Column(TypeName="VARCHAR(50)] annotation.
If you are a dotConnect for MySQL user, we advise you to take a look at this article. If you use some other provider, we advise you to contact its vendor.
I'm creating a DB table using hbm2ddl with Java code similar to the following:
#Entity
public class Filter {
public enum Type {
TypeA, TypeB;
}
#Enumerated(EnumType.STRING)
private Type type;
}
It works fine, but for "type" a VARCHAR column is created, i.e. the DDL code looks like this:
CREATE TABLE IF NOT EXISTS `filter` (`type` varchar(255) DEFAULT NULL)
But what I want to have is this:
CREATE TABLE IF NOT EXISTS `filter` (`type` enum('TypeA','TypeB') NOT NULL)
Is this possible to declare in Hibernate, preferred with annotations?
Or is there a way to extend SchemaUpdate and overwrite the method that renders the alter script part for enumerated field the way I like it?
Background: The same database is used in a PHP part of the project and I want to prevent that invalid values are inserted.
Although it seems there is no way to handle MySQL enums 100% automatically, as pointed out by Lucas on his answer, there is actually a simple way to contour it. You may use columnDefinition attribute on #Column annotation, which seems to be specifically designed to generate custom DDL code.
See the documentation excerpt describing the attribute:
(Optional) The SQL fragment that is used when generating the DDL for the column.
Defaults to the generated SQL to create a column of the inferred type.
The NOT NULL restriction is quite standard, and is supported by another attribute nullable.
Thus, your property definition would look like this:
#Enumerated(EnumType.STRING)
#Column(columnDefinition = "enum ('TypeA', 'TypeB')", nullable = false)
private Type type;
I believe that's going to be complicated, since the java.sql.Types, which define the sql types treated by java, does not have enum type (since it's not a standardized type according to SQL-92).
If that was the case you could create a hibernate custom UserType extending the EnumType and setting the sqlType accordingly, but since java.sql.Types doesn't handle it I don't see how to use native sql enum.
best regards!
We have the following entity relationships where a User belongs to a particular Organization. My queries either look like "select * from User where org=:org" or "select * from User where org=:org and type=:type"
I have separate indexes on the User class. The first query will be fine, because of the Index on the foreign key element. Does the second query mandate a multi columnindex on org and type columns. If so how should I annotate to create one such index.
#Entity
class User {
...
#ManyToOne
#ForeignKey
#Index
Organization org;
#Index
Type type;
...
}
This is doable using the Hibernate specific #Table annotation. From the documentation:
2.4.1 Entity
...
#Table(appliesTo="tableName", indexes = { #Index( name="index1", columnNames={"column1", "column2"} ) } ) creates the defined indexes on the columns of table tableName. This can be applied on the primary table or any secondary table. The #Tables annotation allows your to apply indexes on different tables. This annotation is expected where #javax.persistence.Table or #javax.persistence.SecondaryTable(s) occurs.
Reference
Hibernate Annotations Reference Guide
2.4. Hibernate Annotation Extensions
As you can read in JSR-000338 Java Persistence 2.1 Proposed Final Draft Specification:
11.1.23 Index Annotation
The Index annotation is used in schema generation. Note that it is not necessary to specify an index for a primary key, as the primary key index will be created automatically, however, the Index annotation may be used to specify the ordering of the columns in the index for the primary key.
#Target({}) #Retention(RUNTIME)
public #interface Index {
String name() default "";
String columnList();
boolean unique() default false;
}
The syntax of the columnList element is a column_list, as follows:
column::= index_column [,index_column]*
index_column::= column_name [ASC | DESC]
The persistence provider must observe the specified ordering of the
columns.
If ASC or DESC is not specified, ASC (ascending order) is
assumed.
Usage example:
#Table(indexes = {
#Index(columnList = "org,type"),
#Index(columnList = "another_column")})
Yes, it is possible using JPA 2.1 as seen in the specification here:
http://download.oracle.com/otndocs/jcp/persistence-2_1-pfd-spec/index.html
on page 445 it states that
The Index annotation is used in schema generation
columnList (Required) The names of the columns to be included in the index.
An example of usage can be seen here:
http://java-persistence-performance.blogspot.co.uk/2013/03/but-what-if-im-not-querying-by-id.html
It seems that the syntax is the same or very similar to Hibernate.