Map inheritance from generic class in Linq To SQL - linq-to-sql

I'm trying to map my inheritance hierarchy to DB using Linq to SQL:
Inheritance is like this, classes are POCO, without any LINQ to SQL attributes:
public interface IStage
{ ... }
public abstract class SimpleStage<T> : IStage where T : Process
{ ... }
public class ConcreteStage : SimpleStage<ConcreteProcess>
{ ... }
Here is the mapping:
<Database Name="NNN" xmlns="http://schemas.microsoft.com/linqtosql/mapping/2007">
<Table Name="dbo.Stage" Member="Stage">
<Type Name="BusinessLogic.Domain.IStage">
<Column Name="ID" Member="ID" DbType="Int NOT NULL IDENTITY" IsPrimaryKey="true" IsDbGenerated="true" AutoSync="OnInsert" />
<Column Name="StageType" Member="StageType" IsDiscriminator="true" />
<Type Name="BusinessLogic.Domain.SimpleStage" IsInheritanceDefault="true">
<Type Name="BusinessLogic.Domain.ConcreteStage" IsInheritanceDefault="true" InheritanceCode="1"/>
</Type>
</Type>
</Table>
</Database>
In the runtime I get error:
System.InvalidOperationException was unhandled
Message="Mapping Problem: Cannot find runtime type for type mapping 'BusinessLogic.Domain.SimpleStage'."
Neither specifying SimpleStage, nor SimpleStage<T> in mapping file helps - runtime keeps producing different types of errors.
DC is created like this:
StreamReader sr = new StreamReader(#"MappingFile.map");
XmlMappingSource mapping = XmlMappingSource.FromStream(sr.BaseStream);
DataContext dc = new DataContext(#"connection string", mapping);
If Linq to SQL doesn't support this, could you, please, advise some other ORM, which does.
Thanks in advance,
Regards!
Ksenia

I found the answer myself, after I looked into IL of my generic class.
In IL its name looks like SimpleStage`1<...> so the issue with mapping file was fixed when I wrote
<Type Name="BusinessLogic.Domain.SimpleStage`1" ...

Have you added the reference to the files and also are you importing the references with using statements? OR using the fully qualified class names?

I think it's because of the generic type T in SimpleStage: it can't produce internally a mapping lookup table for SimpleStage as T is generic.

Related

liquibase exception unknown data type "JSON"

my application use jhipster with mysql and liquibase, and mysql version is 5.7.20 which support json column, and I use ObjectMapper to map json column and java object, and it works, the column type is json, but when the liquibase in involved (./mvnw package -Pprod dockerfile:build), there will be exception like "unknown data type 'JSON'" and the test will be failed, no docker image generated.
I change a bit in 20180410012441_added_entity_Ability.xml for that json column:
<column name="abilities" type="json">
<constraints nullable="true"/>
</column>
in my domain class, the json related field is like:
#Type(type = "json")
#Column(columnDefinition = "json")
private List<Skill> abilities = new ArrayList<>();
I suspect the problem is related for that xml column/type definition, liquibase does not support json keyword, I have no idea what should be there for correct type.
Could someone help please? very appreciated.
=========================================================
update 9:01 PM Beijing time
I add a changeSet as "
<changeSet id="20180415081741-1" author="jhipster">
<sql dbms="mysql" endDelimiter="\nGO" splitStatements="true"
stripComments="true">ALTER TABLE `ability` ADD `abilities` json DEFAULT NULL</sql>
</changeSet>
then I issue "./mvnw package -Pprod dockerfile:build", another exception which seemingly hibernate related:
2018-04-15 20:56:52.186 ERROR 23936 --- [ main] o.h.metamodel.internal.MetadataContext : HHH015007: Illegal argument on static metamodel field injection : com.james.app.domain.Ability_#abilities; expected type : org.hibernate.metamodel.internal.SingularAttributeImpl; encountered type : javax.persistence.metamodel.ListAttribute
For those who still have this problem in either H2 and PostgreSQL database even after defining a TypeDef ...etc, after doing the following:
#Entity
#TypeDef(name = "jsonb", typeClass = com.vladmihalcea.hibernate.type.json.JsonBinaryType.class)
class SomeEntity {
// ...
#Type(type = "jsonb")
#Column(columnDefinition = "jsonb")
private List<Skill> abilities = new ArrayList<>();
// ...
}
You need to register the type by extending the Database dialect and using that extended dialect as the dialect instead of the original dialect:
1st define the new extended dialect:
import org.hibernate.dialect.PostgreSQL10Dialect;
import javax.inject.Inject;
public class AMPostgresDialect
extends PostgreSQL10Dialect
{
#Inject
public AMPostgresDialect()
{
super();
registerColumnType( Types.JAVA_OBJECT, "jsonb" );
}
}
and if you have an H2 Database for the testing profile:
import org.hibernate.dialect.H2Dialect;
import java.sql.Types;
public class DhisH2Dialect extends H2Dialect
{
public DhisH2Dialect()
{
super();
registerColumnType( Types.JAVA_OBJECT, "text" );
registerColumnType( Types.JAVA_OBJECT, "json" );
}
and then in the application-*.yml properties file you use those extended dialects instead of the original one.
Change the liquibase column type as jsonb and try.
<column name="abilities" type="jsonb">
<constraints nullable="true"/>
</column>
Add the type and column definition as jsonb.
#Type(type = "jsonb")
#Column(columnDefinition = "jsonb")
private List<Skill> abilities = new ArrayList<>();
Considering you are using Oracle, Check this https://docs.oracle.com/en/database/oracle/oracle-database/12.2/adjsn/creating-a-table-with-a-json-column.html#GUID-E6CC0DCF-3D72-41EF-ACA4-B3BF54EE3CA0 for creating table with JSON column. Use the command in <sql> </sql> in liquibase.

How to solve circular reference in json serializer caused by Many TO Many hibernate bidirectional mapping?

I am trying to serialize POJO to JSON but stuck in circular reference problem. I know how to handle one to many and reverse relationships using the #JsonBackReference and #JsonManagedReference.
My problem is with bidirectional many-to-many relation(eg a student can have many courses and each course can have many students enrolled), parent references child and child references back to parent and here my serializer dies. As per my understanding I cannot use #JsonBackReference here as value type of the property must be a bean: it can not be a Collection, Map, Array or enumeration.
Can some one please advise how I can handle this scenario?
You can use #JsonIgnoreProperties("someField") on one of the sides of the relations (the annotation is class-level). Or #JsonIgnore
As #Bozho have answered to use #JsonIgnoreProperties, try this, it worked for me.
Below are my models with #JsonIgnoreProperties:
#Entity
public class Employee implements Serializable{
#ManyToMany(fetch=`enter code here`FetchType.LAZY)
#JoinTable(name="edm_emp_dept_mappg",
joinColumns={#JoinColumn(name="emp_id", referencedColumnName="id")},
inverseJoinColumns={#JoinColumn(name="dept_id", referencedColumnName="id")})
#JsonIgnoreProperties(value="employee")
Set<Department> department = new HashSet<Department>();
}
#Entity
public class Department implements Serializable {
#ManyToMany(fetch=FetchType.LAZY, mappedBy="department")
#JsonIgnoreProperties(value="department")
Set<Employee> employee = new HashSet<Employee>();
}
In value attribute of #JsonIgnoreProperties, we need to provide the collection type property of counter(related) model.
You can also use Dozer mapping to convert a POJO to a Map and exclude fields. For example if we have two classes PojoA and PojoB having bi-directional relationships, we define mapping like this
<mapping map-id="mapA" map-null="false">
<class-a>com.example.PojoA</class-a>
<class-b>java.util.Map</class-b>
<field>
<a>fieldA</a>
<b>this</b>
</field>
<field map-id="mapB">
<a>pojoB</a>
<b>this</b>
<b-hint>java.util.Map</b-hint>
</field>
</mapping>
<mapping map-id="mapB" map-null="false">
<class-a>com.example.PojoB</class-a>
<class-b>java.util.Map</class-b>
<field-exclude>
<a>pojoA</a>
<b>this</b>
</field-exclude>
</mapping>
Then you define a bean setting the above dozer mapping file as a property.
<bean id="mapper" class="org.dozer.DozerBeanMapper">
<property name="mappingFiles">
<list>
<value>dozerMapping.xml</value>
</list>
</property>
</bean>
Then in the class that where you are serializing
public class TestClass
{
#Autowired
DozerBeanMapper mapper;
public Map<String,Object> serializeObject(PojoA pojoA)
{
return ((Map<String, Object>) mapper.map(pojoA, Map.class, "mapA"));
}
}
Dozer manual here.
Expounding on what #Bozho already mentioned...
I'm stuck with Jackson 1 right now because I'm using Google Cloud Endpoints, so this might still help some people even though Jackson 2 has been out for a while. Even though I don't need the whole object deserialized, the reference is still very necessary.
I put #JsonIgnore on the fields causing the circular reference, but then created a new getter for each one so that a flat reference is still returned in my APIs.
#JsonIgnore
private FooClass foo;
public String getFooKey()
...
With Cloud Endpoints, this results in a flat "fooKey" being returned in the GET payload, while omitting "foo".
if you have the collection object let it be
collection<object> listobj
var jsonObj = from c in listobj
select new
{
Prop1 = c.Prop1
...
}
This should work and object you get now can be json serialized and its clean

How to use complex Type params argument in Spring.NET constructor

I am trying to use Spring.NET with a C# application to populate a parameter array (params keyword) constructor argument that is of a complex Type (call it SecretCode, which happens to be an enumerated type.)
Can someone help point me to the documentation to configure the XML file to do this?
For reference, here are relevant code snippets:
public class MyValueSet<T> where T: struct
{
public MyValueSet(params T[] values) {...}
}
public class DerivedClass : MyValueSet<SecretCode> {...}
public enum SecretCode {...}
The hard-coded code I am trying replace with the Spring.NET configuration file is (close enough to) this:
var something = new DerivedClass(SecretCode.One, SecretCode.Two, SecretCode.Fifty-Two);
Thoughts?
I posted the question in order to share the answer I came up with, and to see if anyone who knows Spring.NET more thoroughly had a better answer.
The configuration I ended up with is this:
<object id="myobject" type="DerivedClass, Assembly.Containing.The.DerivedClass">
<constructor-arg name="values">
<list element-type="SecretCode, Assembly.Containing.The.SecretCode.Enumeration">
<value>One</value>
<value>Two</value>
<value>Fifty-Two</value>
</list>
</constructor-arg>
</object>

Mapping a derived class to a table in Linq-to-SQL

I have an abstract base class for audit properties. For brevity say it has one property
Public MustInherit Class AbstractAuditableEntity
...
Public Property CreatedTime() As DateTimeOffset
...
End Class
And then my auditable domain objects inherit from this class
Public Class Source
Inherits AbstractAuditableEntity
...
Public Property SourceId() As String
...
End Class
I have the following table DDL to which I want to map my domain object "Source". Essentially the relationship between each (concrete) domain object and table is 1-1, with each table having the required audit column.
CREATE TABLE Source
(
SourceID VARCHAR(10) NOT NULL,
CreatedTime DATETIMEOFFSET(3) NOT NULL,
CONSTRAINT PK_Source PRIMARY KEY (SourceID))
GO
Using an external mapping file my first attempt to map the class to the table would foolishly be:
<?xml version="1.0" encoding="utf-8"?>
<Database Name="" xmlns="http://schemas.microsoft.com/linqtosql/mapping/2007">
<Table Name="Source" Member="Sources">
<Type Name ="Source">
<Column Name="SourceID" Member="SourceID" IsPrimaryKey="true" CanBeNull="false"/>
<Column Name="CreatedTime" Member="CreatedTime" />
</Type>
</Table>
</Database>
However this generates the following exception:
The column or association 'CreatedTime' in the mapping had no corresponding member in type 'Source'. Mapping members from above root type is not supported.
Within the context of my persistence layer I am not trying to represent an inheritance hierarchy as such, but within the context of my application I am simply using a base class to provided properties required by all my domain objects. With a lot of fiddling with my mapping file (including mapping the audit columns to the base AbstractAuditableEntity type) and reading around, I am unable to achieve what I perceive as quite a straighforward ORM task.
Any thoughts or suggestions would be most welcome!
Thanks
I'm guessing that you are trying to emulate auditing fields like Ruby on Rails updated_on, created_on. If so, here is how I accomplished something similar using this post as a starting point
http://weblogs.asp.net/stevesheldon/archive/2008/02/23/a-method-to-handle-audit-fields-using-linq-to-sql.aspx
I implemented an interface in the Models namespace like so:
public interface IAuditable
{
DateTime CreatedOn { get; set; }
string CreatedBy { get; set; }
DateTime? ChangedOn { get; set; }
string ChangedBy { get; set; }
}
And then extended the partial classes of the data entities that had these fields:
public partial class DataModelIWantToAudit : IAuditable
{
}
And then overrode SubmitChanges on the DataContext to check for the implementation of the interface with the magic of Linq OfType<>:
public override void SubmitChanges(ConflictMode failureMode)
{
//Updates
foreach (var updatedModel in GetChangeSet().Updates.OfType<IAuditable>())
{
updatedModel.ChangedOn = DateTime.Now;
updatedModel.ChangedBy = Membership.GetUser().UserName;
}
//Inserts
foreach (var insertedModel in GetChangeSet().Inserts.OfType<IAuditable>())
{
insertedModel.CreatedOn = DateTime.Now;
insertedModel.CreatedBy = Membership.GetUser().UserName;
}
base.SubmitChanges(failureMode);
}
Hope that helps!
-Kelly
Kelly showed a great sample of how to do it - but you've basically hit one of the limitations of Linq-to-SQL.
It works great if you database table map more or less 1:1 to your domain objects. But it's weak and causes a lot of extra work once this is no longer the case.
In such a case, as soon as you have domain object inheritance and other things that need to be mapped to database tables, you're best bet would be to check out ADO.NET Entity Framework instead. The EF is specifically designed to handle these things - if you ever think "I need to map my objects ......" then you should think EF! :-)
Granted, the current EF shipping in .NET 3.5 SP1 has its warts and annoyances, but the EF 4 that is part of the .NET 4.0 wave (which should ship before the end of this year 2009), should solve a great many of those warts!
Check out the ADO.NET Entity Framework team blog for some teasers of what EF4 will bring us all!
Marc

Jibx always gives "Error during validation: null"

I'm really stumped on this incredibly simple mapping. It looks just like one of the examples even. If I comment out the internal structure, it'll run the binding compiler successfully. If I put the internal structure back in, it fails. Note that the internal structure is just defining the XML. This is basically example5 of the JIBX tutorial examples.
<binding>
<mapping name="RequestTransaction" class="TransactionRequest">
<value name="version" set-method="setVersion" get-method="getVersion" style="attribute" />
<structure name="transHeader">
<value name="requestCount" set-method="setRequestCount" get-method="getRequestCount"/>
</structure>
</mapping>
<binding>
Then I get the following error on the jibx compile:
Error: Error during validation: null; on mapping element at (line 2, col 97, in jibx-binding.xml)
I'm absolutely stumped and out of ideas. Google shows nothing useful.
The <structure> is arguably the most important concept in JiBX binding because it allows you to map arbitrary XML to your Java classes without forcing you to create bloated and ugly layers of nested Java objects and classes to match the XML design.
In this case your binding declares that you have an XML element named <transHeader> that will not be present in your Java class.
With some slight fixes to your XML format, your binding works perfectly. I assume the fact that your binding has two <binding> open tags rather than and open and close <binding></binding> is a typo, because you said you got it to work without the structure. Also add <?xml version="1.0"?> at the top of your binding file. Those two XML mods allow the JiBX 1.2 binding compiler to work with the following Java class:
(Note: you didn't provide the Java class this binding is for so I had to reconstruct it from the info you put in the binding file. The obvious side effect of this is that I reconstructed a class that will work with this binding. But the simple fact is that a JiBX binding by design contains all the info you need to know about the class and the XML.)
public class TransactionRequest {
private String version;
private int requestCount;
public void setVersion(String ver) {
version = ver;
}
public String getVersion() {
return version;
}
public void setRequestCount(int count) {
requestCount = count;
}
public int getRequestCount() {
return requestCount;
}
}
compile the class then run the binding compiler with:
>java -jar jibx-bind.jar jibx-binding.xml
To test it I used the following sample.xml:
(Note: you also didn't provide the XML you are trying to map so again I created a sample based on what you did provide)
<?xml version="1.0"?>
<RequestTransaction version="0.1">
<transHeader>
<requestCount>3</requestCount>
</transHeader>
</RequestTransaction>
Running the test uses the following code:
public static void main(String[] argz) {
String fileName = "./sample.xml";
IBindingFactory bfact = null;
IUnmarshallingContext uctx = null;
TransactionRequest sample = null;
try {
bfact = BindingDirectory.getFactory(TransactionRequest.class);
uctx = bfact.createUnmarshallingContext();
InputStream in = new FileInputStream(fileName);
sample = (TransactionRequest)uctx.unmarshalDocument(in, null);
System.out.println(sample.getRequestCount());
System.out.println(sample.getVersion());
}
catch (Exception e) {
e.printStackTrace();
}
}
And it runs successfully.
It's been a while now, but I found it was related to inheritance. I needed to give mappings for everything in the inheritance tree, including interfaces as I recall.
I ended up creating a wrapper object, which I've found seems to be the easiest way to use JIBX in general. Trying to map a true domain class causes tendrils into every class that class touches and I have to unjar everything so JIBX can find the classes, including 3rd party libs.