I am setting the type for sql query result set as List in java. I am trying to convert it into
a dto.
When I see the List<Object[]> structure from query. It shows
resultList-ArrayList<E>
[0....9999]
[0..99]
[0]=Object[3]
[0]="jjj"
[1]="8787"
[2]="7686"
So is this expected. How can I access the object values here(jjj,8787...) by setting it to dto.
I tried something like this
List<Dto> dtoList = resultList.stream().map(obj->{
Dto dt = new Dto()
dt.setName(obj[0]);
).collect(Collectors.toList())
This is not correct as I am not able to access the object
Should I do another level of iteration in order to reach that object or is my generic type for result set is right
Thanks
Try this:
Object[] inner = new Object[]{"jjj", "8787", "7686"};
Object[] outer = new Object[]{inner};
List<Object[]> resultList = new ArrayList<>();
resultList.add(outer);
List<Dto> dtos;
dtos = resultList.stream()
.flatMap((Object[] objArr) -> {
Object[] subArr = (Object[]) objArr[0];
return Arrays.asList(subArr).stream()
.map(obj -> obj.toString());
})
.map(name -> {
Dto dto = new Dto();
dto.setName(name);
return dto;
})
.collect(Collectors.toList());
Related
I using bind variable to do a batch update using below code
`var balanceUpdate = dslContext.batch(
dslContext.update(BALANCE)
.set(BALANCE.BALANCE, (BigDecimal) null)
.where(BALANCE.ID.eq((String) null)));
balances.forEach(balance -> {
balanceUpdate.bind(
balance.getAmount()
balance.Id);
});
int[] execute = balanceUpdate.execute();
`
Above code work well, but now i want to use bind with array of arguments like
var balanceUpdate = dslContext.batch(
dslContext.update(BALANCE)
.set(BALANCE.BALANCE, (BigDecimal) null)
.where(BALANCE.ID.eq((String) null)));
var arguments = balances.stream()
.map(balance ->
new Object[] {
balance.getAmount(),
balance.Id
}).collect(Collectors.toList());
int[] execute = balanceUpdate.bind(arguments).execute();
I get exception
java.lang.ArrayStoreException: arraycopy: element type mismatch: can not cast one of the elements of java.lang.Object[] to the type of the destination array, java.math.BigDecimal
at org.jooq_3.14.4.ORACLE12C.debug(Unknown Source)
at java.base/java.util.Arrays.copyOf(Arrays.java:3722)
at org.jooq.tools.Convert.convertArray(Convert.java:357)
at org.jooq.tools.Convert.convertArray(Convert.java:345)
at org.jooq.tools.Convert$ConvertAll.from(Convert.java:603)
at org.jooq.tools.Convert.convert0(Convert.java:392)
at org.jooq.tools.Convert.convert(Convert.java:384)
at org.jooq.tools.Convert.convert(Convert.java:458)
at org.jooq.tools.Convert.convertArray(Convert.java:363)
at org.jooq.tools.Convert.convertArray(Convert.java:345)
at org.jooq.tools.Convert$ConvertAll.from(Convert.java:614)
at org.jooq.tools.Convert.convert0(Convert.java:392)
at org.jooq.tools.Convert.convert(Convert.java:384)
at org.jooq.tools.Convert.convert(Convert.java:458)
at org.jooq.impl.AbstractDataType.convert(AbstractDataType.java:534)
at org.jooq.impl.DefaultDataType.convert(DefaultDataType.java:86)
at org.jooq.impl.DSL.val(DSL.java:24409)
at org.jooq.impl.DSL.val(DSL.java:24377)
at org.jooq.impl.Tools.field(Tools.java:1794)
at org.jooq.impl.Tools.fields(Tools.java:1865)
at org.jooq.impl.BatchSingle.executePrepared(BatchSingle.java:226)
at org.jooq.impl.BatchSingle.execute(BatchSingle.java:170)
According docs it should work ? Atleast it works without explicit casting when using jdbc. Is there anyway to get it work to sent bind variables only once instead of many times like in first example?
I think you're calling the wrong BatchBindStep.bind(Object...) method, or at least not in the way you're expecting. There's currently no overload accepting a collection of type List<Object[]>. So, what you should do instead is create an Object[][] type for your bind variable sets:
Object[][] arguments = balances
.stream()
.map(balance -> new Object[] {
balance.getAmount(),
balance.Id
}).toArray();
Following a question where the answer provided a working solution to serialize / deserialize discriminated unions (IgnoreMissingMember setting doesn't seem to work with FSharpLu.Json deserializer)
I have now a practical case where this fails (although it works in simpler cases).
here is the test code:
open System.Collections.Generic
open Microsoft.FSharpLu.Json
open Newtonsoft.Json
open Newtonsoft.Json.Serialization
// set up the serialization / deserialization based on answer from:
// https://stackoverflow.com/questions/62364229/ignoremissingmember-setting-doesnt-seem-to-work-with-fsharplu-json-deserializer/62364913#62364913
let settings =
JsonSerializerSettings(
NullValueHandling = NullValueHandling.Ignore,
Converters = [| CompactUnionJsonConverter(true, true) |]
)
let serialize object =
JsonConvert.SerializeObject(object, settings)
let deserialize<'a> object =
JsonConvert.DeserializeObject<'a>(object, settings)
// define the type used
type BookSide =
| Bid
| Ask
type BookEntry =
{
S : float
P : float
}
type BookSideData =
Dictionary<int, BookEntry>
type BookData =
{
Data: Dictionary<BookSide, BookSideData>
}
static member empty =
{
Data = Dictionary<BookSide, BookSideData>(dict [ (BookSide.Bid, BookSideData()); (BookSide.Ask, BookSideData()) ])
}
// make some sample data
let bookEntry = { S=3.; P=5. }
let bookData = BookData.empty
bookData.Data.[BookSide.Bid].Add(1, bookEntry)
// serialize. This part works
let s = serialize bookData
// deserialize. This part fails
deserialize<BookData> s
the serialized test data will look like this:
{"Data":{"Bid":{"1":{"S":3.0,"P":5.0}},"Ask":{}}}
but deserializing will crash like this:
Could not convert string 'Bid' to dictionary key type 'FSI_0023+BookSide'. Create a TypeConverter to convert from the string to the key type object.
although the serialization / deserialization of the DU through FSharpLu which has a DU converter.
The reason I am trying to find some automated solution, vs writing a custom TypeConverter (besides the fact I've never done it) is that I have a lot of types I do not control to go through.
Here is a fiddle:
https://dotnetfiddle.net/Sx0k4x
Your basic problem is that you are using BookSide as a dictionary key -- but this is an f# union which makes it a complex key -- one not immediately convertible to and from a string. Unfortunately Json.NET does not support complex dictionary keys out of the box as is stated in its Serialization Guide:
When serializing a dictionary, the keys of the dictionary are converted to strings and used as the JSON object property names. The string written for a key can be customized by either overriding ToString() for the key type or by implementing a TypeConverter. A TypeConverter will also support converting a custom string back again when deserializing a dictionary.
There are two basic approaches to handling this issue:
Implement a TypeConverter as is shown in, e.g., Not ableTo Serialize Dictionary with Complex key using Json.net.
Serialize the dictionary as an array of key/value pair objects e.g. as is shown in Serialize dictionary as array (of key value pairs).
Since your data model includes dictionaries with a variety of keys (DU, strings and ints) the second solution would appear to be the only possibility. The following DictionaryConverter should have the necessary logic:
let inline isNull (x:^T when ^T : not struct) = obj.ReferenceEquals (x, null)
type Type with
member t.BaseTypesAndSelf() =
t |> Seq.unfold (fun state -> if isNull state then None else Some(state, state.BaseType))
member t.DictionaryKeyValueTypes() =
t.BaseTypesAndSelf()
|> Seq.filter (fun i -> i.IsGenericType && i.GetGenericTypeDefinition() = typedefof<Dictionary<_,_>>)
|> Seq.map (fun i -> i.GetGenericArguments())
type JsonReader with
member r.ReadAndAssert() =
if not (r.Read()) then raise (JsonReaderException("Unexpected end of JSON stream."))
r
member r.MoveToContentAndAssert() =
if r.TokenType = JsonToken.None then r.ReadAndAssert() |> ignore
while r.TokenType = JsonToken.Comment do r.ReadAndAssert() |> ignore
r
type internal DictionaryReadOnlySurrogate<'TKey, 'TValue>(i : IDictionary<'TKey, 'TValue>) =
interface IReadOnlyDictionary<'TKey, 'TValue> with
member this.ContainsKey(key) = i.ContainsKey(key)
member this.TryGetValue(key, value) = i.TryGetValue(key, &value)
member this.Item with get(index) = i.[index]
member this.Keys = i.Keys :> IEnumerable<'TKey>
member this.Values = i.Values :> IEnumerable<'TValue>
member this.Count = i.Count
member this.GetEnumerator() = i.GetEnumerator()
member this.GetEnumerator() = i.GetEnumerator() :> IEnumerator
type DictionaryConverter () =
// ReadJson adapted from this answer https://stackoverflow.com/a/28633769/3744182
// To https://stackoverflow.com/questions/28451990/newtonsoft-json-deserialize-dictionary-as-key-value-list-from-datacontractjsonse
// By https://stackoverflow.com/users/3744182/dbc
inherit JsonConverter()
override this.CanConvert(t) = (t.DictionaryKeyValueTypes().Count() = 1) // If ever implemented for IReadOnlyDictionary<'TKey, 'TValue> then reject DictionaryReadOnlySurrogate<'TKey, 'TValue>
member private this.ReadJsonGeneric<'TKey, 'TValue> (reader : JsonReader, t : Type, existingValue : obj, serializer : JsonSerializer) : obj =
let contract = serializer.ContractResolver.ResolveContract(t)
let dict = if (existingValue :? IDictionary<'TKey, 'TValue>) then existingValue :?> IDictionary<'TKey, 'TValue> else contract.DefaultCreator.Invoke() :?> IDictionary<'TKey, 'TValue>
match reader.MoveToContentAndAssert().TokenType with
| JsonToken.StartArray ->
let l = serializer.Deserialize<List<KeyValuePair<'TKey, 'TValue>>>(reader)
for p in l do dict.Add(p)
dict :> obj
| JsonToken.StartObject ->
serializer.Populate(reader, dict)
dict :> obj
| JsonToken.Null -> null // Or throw an exception if you prefer
| _ -> raise (JsonSerializationException(String.Format("Unexpected token {0}", reader.TokenType)))
override this.ReadJson(reader, t, existingValue, serializer) =
let keyValueTypes = t.DictionaryKeyValueTypes().Single(); // Throws an exception if not exactly one.
let m = typeof<DictionaryConverter>.GetMethod("ReadJsonGeneric", BindingFlags.NonPublic ||| BindingFlags.Instance ||| BindingFlags.Public);
m.MakeGenericMethod(keyValueTypes).Invoke(this, [| reader; t; existingValue; serializer |])
member private this.WriteJsonGeneric<'TKey, 'TValue> (writer : JsonWriter, value : obj, serializer : JsonSerializer) =
let dict = value :?> IDictionary<'TKey, 'TValue>
let keyContract = serializer.ContractResolver.ResolveContract(typeof<'Key>)
// Wrap the value in an enumerator or read-only surrogate to prevent infinite recursion.
match keyContract with
| :? JsonPrimitiveContract -> serializer.Serialize(writer, new DictionaryReadOnlySurrogate<'TKey, 'TValue>(dict))
| _ -> serializer.Serialize(writer, seq { yield! dict })
()
override this.WriteJson(writer, value, serializer) =
let keyValueTypes = value.GetType().DictionaryKeyValueTypes().Single(); // Throws an exception if not exactly one.
let m = typeof<DictionaryConverter>.GetMethod("WriteJsonGeneric", BindingFlags.NonPublic ||| BindingFlags.Instance ||| BindingFlags.Public);
m.MakeGenericMethod(keyValueTypes).Invoke(this, [| writer; value; serializer |])
()
Which you would add to settings as follows:
let settings =
JsonSerializerSettings(
NullValueHandling = NullValueHandling.Ignore,
Converters = [| CompactUnionJsonConverter(true, true); DictionaryConverter() |]
)
And generates the following JSON for your bookData:
{
"Data": [
{
"Key": "Bid",
"Value": [
{
"Key": 1,
"Value": {
"S": 3.0,
"P": 5.0
}
}
]
},
{
"Key": "Ask",
"Value": []
}
]
}
Notes:
The converter works for all Dictionary<TKey, TValue> types (and subtypes).
The converter detects whether the dictionary keys will be serialized using a primitive contract, and if so, serializes the dictionary compactly as a JSON object. If not the dictionary is serialized as an array. You can observe this in the JSON shown above: the Dictionary<BookSide, BookSideData> dictionary is serialized as a JSON array, and the Dictionary<int, BookEntry> dictionary is serialized as a JSON object.
During deserialization the converter detects whether the incoming JSON value is an array or object, and adapts as required.
The converter is only implemented for the mutable .Net Dictionary<TKey, TValue> type. The logic would require some slight modification to deserialize the immutable Map<'Key,'Value> type.
Demo fiddle here.
I am trying to convert a Linq result in to a datatable
I have a linq that is created from a dataset of many tables. It returns results, but I need to get the results in to a new datatable.
Examples I have seen say I sould be able to use .CopyToDataTable But for some reason this doesn't work?
I have noticed that I can to .ToArray perhaps I can then turn the array in to a datatable? Seems line an unnecessary step?
Here is my query: (it works)
Dim R2 = From Inq In DS.Tables!CNLocalInquiry.AsEnumerable()
Join Cust In DS.Tables!CustomerID.AsEnumerable() On Inq.Field(Of Integer)("CNLocalInquiry_Id") Equals Cust.Field(Of Integer)("CNLocalInquiry_Id")
Select New With {.date = Inq.Field(Of String)("date"),
.CName = Cust.Field(Of String)("CustomerNumber"),
.Name = Cust.Field(Of String)("name")}
Dim MemberInq as new datatable
MemberInq = R2.CopyToDataTable() <-- this doesn't work
This is what my query returns:
(this is the easy to code way... this will not be performant for large datasets)
public static class ToolsEx
{
public static DataTable ToDataTable<T>(this IEnumerable<T> items)
{
var t = typeof(T);
var dt = new DataTable(t.Name);
var props = t.GetProperties()
.Select(p => new { N = p.Name, Getter = p.GetGetMethod() })
.Where(p => p.Getter != null)
.ToList();
props.ForEach(p => dt.Columns.Add(p.N));
foreach (var item in items)
dt.Rows.Add(props.Select(p => p.Getter.Invoke(item, null)).ToArray());
return dt;
}
}
I've saved this as an extension method and it's always worked perfectly:
https://msdn.microsoft.com/en-us/library/bb669096.aspx
Examples here:
https://msdn.microsoft.com/en-us/library/bb386921.aspx
Hope that does the trick!
I want to convert my class to a Map so I'm using Serialization package. From the example it looks simple:
var address = new Address();
address.street = 'N 34th';
address.city = 'Seattle';
var serialization = new Serialization()
..addRuleFor(Address);
Map output = serialization.write(address);
I expect to see an output like {'street' : 'N 34th', 'city' : 'Seattle'} but instead it just output something I-don't-know-what-that-is
{"roots":[{"__Ref":true,"rule":3,"object":0}],"data":[[],[],[],[["Seattle","N 34th"]]],"rules":"{\"roots\":[{\"__Ref\":true,\"rule\":1,\"object\":0}],\"data\":[[],[[{\"__Ref\":true,\"rule\":4,\"object\":0},{\"__Ref\":true,\"rule\":3,\"object\":0},{\"__Ref\":true,\"rule\":5,\"object\":0},{\"__Ref\":true,\"rule\":6,\"object\":0}]],[[],[],[\"city\",\"street\"]],[[]],[[]],[[]],[[{\"__Ref\":true,\"rule\":2,\"object\":0},{\"__Ref\":true,\"rule\":2,\"object\":1},\"\",{\"__Ref\":true,\"rule\":2,\"object\":2},{\"__Ref\":true,\"rule\":7,\"object\":0}]],[\"Address\"]],\"rules\":null}"}
Serialization is not supposed to create human-readable output. Maybe JSON output is more what you look for:
import dart:convert;
{
var address = new Address();
..address.street = 'N 34th';
..address.city = 'Seattle';
var encoded = JSON.encode(address, mirrorJson);
}
Map mirrorJson(o) {
Map map = new Map();
InstanceMirror im = reflect(o);
ClassMirror cm = im.type;
var decls = cm.declarations.values.where((dm) => dm is VariableMirror);
decls.forEach((dm) {
var key = MirrorSystem.getName(dm.simpleName);
var val = im.getField(dm.simpleName).reflectee;
map[key] = val;
});
return map;
}
The new Address() creates a full prototype object which is what you are seeing. That being said, they could have done something to avoid part of those, but if you want to restore the object just the way it is, that's necessary.
To see the full content of an object you use the for() instruction in this way:
for(obj in idx) alert(obj[idx]);
You'll see that you get loads of data this way. Without the new Address() it would probably not be that bad.
Serialization won't help you here...
You might give a try to JsonObject library, and maybe go through this in depth explanation how to do what you are trying to do using mirrors.
I am using the System.Linq.Data library provided here - http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
I have the following query which works great and returns an Iqueryable
IQueryable customer =
ctx.Customers.Where(cust => true).Select("new("Name,Address")");
However, how do I access these returned columns? I cannot access them using a lambda expression as follows:
var test = customer.Where(cust=>cust.Name == "Mike").First();
"cust.Name" in the above case cannot be resolved. It does not exist in the list of methods/properties for "cust".
Am i assuming something wrong here. I understand that I am working with an anonymous type. Do I have to create a DTO in this case?
For any IQueryable you have property called ElementType.
You can use it to get the properties as explained below
IQueryable query = from t in db.Cities
selec new
{
Id = t.Id,
CityName = t.Name
};
if(query!=null)
{
Type elementType = query.ElementType;
foreach(PropertyInfo pi in elementType.GetProperties())
{
}
}
Try foreach loop:
var a = _context.SENDERS.Select(x=>new { Address=x.ADDRESS, Company=x.COMPANY });
foreach(var obj in a)
{
Console.WriteLine(obj.Address);
Console.WriteLine(obj.Company);
}