Is there a way to define NamedQueries outside of entity? - configuration

I use Netbeans as IDE and use the wizards to generate Entities. If I want to define custom NamedQueries (not the ones auto generated) how can I define those outside of the entity so I don't lose them if I have to recreate the entity using the wizard?

You can add the custom named queries instead like:
<persistence-unit>
...
<named-query name="xxxxxx">
<query>
<![CDATA[
SELECT x FROM XXXXXXXX x
]]>
</query>
</named-query>
</persistence-unit>

Related

Liquibase use a variable to set changeset author

Is it possible to use some kind of variable or property to set the changeset author in a liquibase formatted sql file.
I have tried to set a property in a chnagelog.xml and using the property for the author as show below.
changelog.xml
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.8.xsd">
<property name="author" value="my-author"/>
<include file="sql/test_schema.sql"/>
</databaseChangeLog>
And test_schemal.sql
--liquibase formatted sql
--changeset ${author}:1
CREATE SCHEMA IF NOT EXISTS test_schema;
--rollback DROP SCHEMA IF EXISTS test_schema;
However, the author is not set to the author property, "my-author".
I think this could also be done with terraform templating, but is there a way to do this using only liquibase functionality?
Liquibase allows dynamic substitution of properties in changelog files. We can configure multiple properties inside a file and then use them wherever required. In your case, we can just configure property "authorName" with some value and then use it in changelog file using ${authorName} syntax.
Whatever Jorge has mentioned in his answer is correct. Liquibase assigns or prioritizes value for configured property in below order:
As an attribute passed to your liquibase runner.
As a JVM sytem property
As an environment variable
As a CLI attribute if you are running liquibase through command line
In liquibase.properties file
In the parameters block (property element of the DATABASECHANGELOG table)
You can do it as below example code snippet:
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.8.xsd">
<changeSet author="${authorName}" id="some-unique-id" dbms="${dbType}" context="some-context">
**My SQL query/ transactional logic goes here**
</changeSet>
</databaseChangeLog>
In liquibase.properties file, I will configure these properties as follows:
authorName=Rakhi
dbType=PostgreSQL
Note: above example is using 2 properties (authorName and dbType). You can use only authorName or even more than that.
If you need help with creating "liquibase.properties" file, visit this link
Cheers!
Using property substitution in your changelog
Liquibase allows you to use different ways to can set property values. Liquibase assigns these values in the order specified below:
As an attribute passed to your Liquibase runner.
As a JVM system property.
As an environment variable.
As a CLI attributes if executed from the command line
As a CLI attributes if executed from the command line
command_line parameter if executed from the command line
In the parameters block (property element) of the DATABASECHANGELOG file itself
Check this liquibase doc

Liquibase script for MYSQL

I have a liquibase xml script. When I run it on Postgres I don't face any problem but when I run it for MYSQL it gives error when the structure is of the following type:-
<insert tableName="user_table">
<column name="id" valueComputed="(select max(id)+1 from user_table)"/>
<column name="name" value="someName"/>
</insert>
When the above script is executed for MYSQL it gives error:-
You can't specify target table 'user_table' for update in FROM clause.
I found a solution to this by using alias like this :-
<insert tableName="user_table">
<column name="id" valueComputed="(select max(id)+1 from (Select * from user_table) t)" />
<column name="name" value="someName"/>
</insert>
But there are thousands of entries like this. Is there any generic way of doing it so that I don't have to change the script at so many places. Thanks.
The easiest approach would be to just update the XML, either with an simple XML parser program or even a regexp search and replace in your text editor.
Alternately, you can override the standard liquibase logic to look for that particular valueComputed pattern and replace it. There are a couple points you could make the change at:
Override the liquibase.parser.core.xml.XMLCHangeLogSAXParser class, probably the parseToNode() method to search through the generated ParsedNode for valueComputed nodes
Override the liquibase.change.core.InsertDataChange class generateStatements() method or addColumn() method to replace valueComputed fields.
See http://liquibase.org/extensions for more info on writing extensions.

Auto creation of database tables using JDO

I am new to JDO and MySQL. In my project, i want that all entities should be converted in table automatically.
I had start using the JDO and defined properties like this,
javax.jdo.PersistenceManagerFactoryClass=org.datanucleus.api.jdo.JDOPersistenceManagerFactory
datanucleus.autoCreateSchema=true
datanucleus.validateTables=false
datanucleus.validateConstraints=false
datanucleus.query.sql.allowAll = true
javax.jdo.option.ConnectionDriverName=com.mysql.jdbc.Driver
javax.jdo.option.ConnectionURL=jdbc:mysql://127.0.0.1:3306/db_name
javax.jdo.option.ConnectionUserName=user
javax.jdo.option.ConnectionPassword=123456
javax.jdo.option.Mapping=hsql
Sample entity:
#PersistenceCapable(identityType = IdentityType.APPLICATION, table = "heartbeat")
public class HeartBeat implements Serializable{
#PrimaryKey
#Column(length=128)
private String userId;
.......
}
Now, when i compile or run my application the tables are not being auto created. I am not sure which property i should use for auto creation of tables based on the entities created.
Please bear with my question as i am new to JDO and MySQL integration.
Thanks in advance.
For JDO, if you want to create the schema for "tables" during the persistence process you tell DataNucleus by using this property, datanucleus.schema.autoCreateTables.
To auto create "columns" use datanucleus.schema.autoCreateColumns, and for "constraints" use datanucleus.schema.autoCreateConstraints. Set the properties to true.
<property name="datanucleus.schema.autoCreateTables" value="true"/>
<property name="datanucleus.schema.autoCreateColumns" value="true"/>
<property name="datanucleus.schema.autoCreateConstraints" value="true"/>
Shortcut for the three, use datanucleus.schema.autoCreateAll and set to true.
<!-- shortcut for the three -->
<property name="datanucleus.schema.autoCreateAll" value="true"/>
You can check the documentations here http://www.datanucleus.org/products/accessplatform_4_1/jdo/schema.html
Defined your JDO properties like this;
datanucleus.schema.autoCreateTables=true
datanucleus.schema.autoCreateColumns=true
datanucleus.schema.autoCreateConstraints=true
or shortcut
datanucleus.schema.autoCreateAll=true

Create a cover index with "Include" columns using nhibernate mapping file

I need to create a non-clustered index with INCLUDE columns (see the <create> tag below). Here's the mapping file:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="MyApp" assembly="MyApp">
<class name="User" table="user" >
<id name="Id" type="Guid" column="user_id">
<generator class="guid.comb"/>
</id>
<property name="Name" column="name" not-null="true" />
<property name="Phone" column="phone" />
<property name="Zipcode" column="zipcode" />
</class>
<database-object>
<create>
CREATE NONCLUSTERED INDEX [IX_user_zipcode_id]
ON User (Zipcode)
INCLUDE (Name, Phone)
</create>
<drop>
DROP INDEX IX_user_zipcode_id
</drop>
<dialect-scope name="NHibernate.Dialect.MsSql2000Dialect"/>
<dialect-scope name="NHibernate.Dialect.MsSql2005Dialect"/>
<dialect-scope name="NHibernate.Dialect.MsSql2008Dialect"/>
</database-object>
</hibernate-mapping>
The problem I'm having is the index is not created at all. Nothing appears to be happening. This is my first time using <database-object> so I may be doing something wrong here.
I'm guessing INCLUDE is Sql Server specific which is why the dialect-scope is there. I know how to create a single and multi-column index, but this is not what I want. I want a single column index on zipcode and all other columns in the User table part of the INCLUDE clause of the query. Is there any way to create this type of index using the mapping file or some other way?
This is probably a long shot, but it would be nice to not have to specify every column but the indexed one in the INCLUDE part of the query... Instead to just let nhibernate add any new columns to the index that are added as properties to the mapping file.
So part of the problem was indeed my lack of understanding the database-object tag due mostly to poor documentation. From what I've gathered, the <create> and <drop> tags are only used when using SchemaExport like so:
Dim schemaExport As SchemaExport = New SchemaExport(NhibernateConfiguration)
schemaExport.Execute(False, True, False)
My app doesn't create the schema using that class. Instead it uses SchemaUpdate so the schema isn't blown away every time (the database may already exist on the users machine):
Dim schemaUpdate As SchemaUpdate = New SchemaUpdate(NhibernateConfiguration)
schemaUpdate.Execute(False, True)
That was the problem. The next logical question to ask is then how do you execute sql using SchemaUpdate. The answer... you can't. See this post: https://forum.hibernate.org/viewtopic.php?f=6&t=969584&view=next
Alas I am left to use raw sql. Maybe some day they will add an <update> tag.

How can I set the Nhibernate type generator to increment when working with SQL Server 2008?

Using HBM files to map my types.
One of my classes uses bag of items called PartnerEnv. One of their fields is set to be the id which should be generated using increment. for some reason I am getting the following error:
could not fetch initial value for increment generator[SQL: SQL not available]
Inner details: "{"Invalid object name 'jj.dbo.Partners2Env'."}"
If I change the generation method to assigned everything is ok.
I will appreciate any help given!
Can you set your Id column on the PartnerEnv table (or whatever that table is called) to an Identity column and then use the following in the .hbm file for that class?
<id name="Id" type="Int32">
<column name="Id" />
<generator class="identity" />
</id>