How do I insert collection of objects using MyBatis 3.x? - collections

I'm a beginner with MyBatis.
I just want to know how to insert a collection of objects from an instance of a class. Say I have a class User related to a Note in one-to-many relationship. I just like to mention that I built my schema using JPA 2 annotations via Hibernate's hbm2ddl. I'll add the key JPA annotations I used in the sample code below.
Here's a sample:
#Entity
public class User {
...
#OneToMany
#JoinColumn(name="user")
public List<Note> getNotes() {...}
...
}
Now, everytime I insert something into User table I have to insert instances into the Note table if the list is not empty. Take note of the #JoinColumn in Note table which should have the id of the inserted User, which I have set to be autogenerated.
Has anyone got something like this working? Thanks.

When using a regular MyBatis XML mapping config you can use something like this:
Java classes:
class EnclosingType {
private List<ElementType> elements;
}
class ElementType {
String a;
String b;
(...)
}
Mapper xml:
<mapper
namespace="my.example.ElementType">
<insert id="insertElements" parameterType="EnlosingType">
INSERT INTO ELEMENTTYPE (enclosingTypeId, column_a, column_b)
VALUES
<foreach item="element" index="index" collection="elements"
open="(" separator="),(" close=")">
#{id}, #{element.a}, #{element.b}
</foreach>
</insert>
</mapper>

Related

Spring Data JPA not parsing response as proper JSON string

We are using Spring MVC 4.1.2 and Spring Data JPA 1.9.0. Everything works fine but when we have custom query with only selected field for a given entity then our json response does not include property name in the response, instead it just included property value.
If I correctly guess, your custom query looks like:
SELECT e.myProperty FROM Entity e [WHERE ...]
The effect of this is that you get a List<Object[]> containing only the array of property values instead of an object that has a field with the name myProperty and its value is the value in the database.
The solution is to create a custom data-transfer object, which has this one field and assign the value in the constructor
public class MyPropertyDTO { // find a better name, though :)
private int myProperty;
public MyPropertyDTO(int myProperty) {
this.myProperty = myProperty;
}
public int getMyProperty() {
return myProperty;
}
}
Then rewrite your query as:
SELECT NEW com.mycompany.MyPropertyDTO(e.myProperty) FROM Entity e [WHERE ...]
In theory you could even use your original Entity class, add a json view on myProperty and create the matching constructor instead of creating a brand new class.

can I add my own classes to entity framework?

I wanted to start using Entity Framework for my projects. A new project which we'll be starting soon, will have an Employee table. I was initially planning to have a IEmployee Interface, which will be implemented by a Manager and Staff classes, which will allow different functionality but will both store data in the Employee table, with a flag in the table distinguishing them.
If I use DB First, and design my Employee table and then use Entity Framework, i know the .tt file will have a partial class Employee. I could then make my own Manager and Staff classes which implement the partial class Employee. But then how would I store that back in the db using Entity Framework? Could I just do something like
// currentManager would be the manager object
dbContext.Emplyee.Add(currentManager);
dbContext.SaveChanges();
would entity framework be ok with this, even though i'm passing a Manager object into Employee to save? Or is there a better way to do this? And same with retrieving, how could I use Entity Framework to get back a Manager or Staff? Would I need to get a Employee back first and then cast it? Something like
var employee = from employees... // get employee
Manager currentManager = (Manager)employee;
Yes, you can use EF DB first and have multiple classes derived from a common base class that are stored in the same database table.
The "flag" you envision is called a discriminator by EF. It is a column in the table that specifies which subtype the record is an instance of.
With database first, you need to tweak the model generated by EF to get this working, but it's fairly straightforward. I think the easiest way to set this up is to
Create the database model in SQL, being sure the Employee table has a NOT NULL property like EmployeeType that can be used as the discriminator. I think this can be any type, but an int will work fine.
Create your EF model ( Add | New Item... | Data | ADO.NET Entity Data Model ), and map the Employee table (and anything else you need).
Double click the generated .edmx file to open the entity framework designer.
Right mouse click on the canvass and select Add New... | Entity and create a Manager entity that derives from Employee. Repeat for Staff. Your designer should look like this:
Right mouse click on Manager and select Table Mapping. In the mapping details, specify that it maps to Employee and add a condition that is When EmployeeType = 1. Do the same for Staff, but make the mapping When EmployeeType = 2.
Last, you need to delete the EmployeeType property from the Employee mapping.
That being done, you can extend the Manager and Staff classes (that will now be generated by EF as partial classes) to have whatever business logic you want, and do queries/etc with EF via the Employees mapping:
public class Manager : Employee
{
public void customManagerMethod() { }
}
public class Staff : Employee
{
public void customStaffMethod() { }
}
class Program
{
static void Main(string[] args)
{
using (var db = new dbfirstEntities())
{
Manager m = new Manager
{
FirstName = "Joe",
LastName = "Bigshot"
};
Staff s = new Staff
{
FirstName = "Joe",
LastName = "Schmoe"
};
db.Employees.Add(m);
db.Employees.Add(s);
db.SaveChanges();
}
}
}

SpringMVC form:options items attribute: what exactly is it expecting?

I'm still new to SpringMVC (and jstl for that matter). I'm trying to populate options in a select from a list of objects. I've found a way to do it using c:forEach, but I keep thinking there HAS to be a way to make the form:options method work.
I've browsed around, and about the closest thing I can find to official documentation on the items attribute is here >> http://static.springsource.org/spring/docs/2.0.x/reference/spring-form.tld.html#spring-form.tld.options
It says the items attribute is for
"The Collection, Map or array of objects used to generate the inner 'option' tags"
My confusion is what kind of Collection, Map, or array of objects it's looking for. What format do they need to be in? Is it looking for a Collection or array of type String specifically? Can I use
List<MyObject>
and if so, what would MyObject have to have in it in order for this to be valid (i.e. methods, variables)?
Currently, when I try to use MyObject, I get an exception that says -
ConverterNotFoundException: No converter found capable of converting from type com.example.MyObject to type java.lang.String
Do I need to make a converter? Where would that go? How would that work? I've googled that error message and haven't really turned up anything specific to what I'm trying to do... (Most are results about Roo)
the MyObject class looks like this:
public class MyObject{
private String company;
private Customer customer;
private Address customerAddress;
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
public Address getCustomerAddress() {
return customerAddress;
}
public void setCustomerAddress(Address customerAddress) {
this.customerAddress = customerAddress;
}
}
and I'm trying to use it as such:
<form:select path="myObjectList">
<form:option value="0"/>
<form:options items="myObjectList" />
</form:select>
Does anyone know specifically what is incorrect about this method? Or, should I be using a
List<String>
to accomplish what I'm doing?
EDIT here's the stack trace >> http://pastebin.com/2c5XBCmG
The Spring Documentation says this about the items attribute of the form:options tag:
The items attribute is typically populated with a collection or array
of item objects. itemValue and itemLabel simply refer to bean
properties of those item objects, if specified; otherwise, the item
objects themselves will be stringified. Alternatively, you may specify
a Map of items, in which case the map keys are interpreted as option
values and the map values correspond to option labels. If itemValue
and/or itemLabel happen to be specified as well, the item value
property will apply to the map key and the item label property will
apply to the map value.
In a nutshell, if you need to use a List of your Custom Beans as the items attribute you need to use also the itemValue and itemLabel attributes. Personally, I'll prefer using Maps -LinkedHashMap instances speciffically- for populating my select tags, but that's a matter of taste.
Adapting an example from the Spring Documentation, your code should look like this:
<form:select path="commandAttribute">
<form:option value="-" label="--Please Select"/>
<form:options items="${countryList}" itemValue="company" itemLabel="company"/>
</form:select>
I'm using the company attribute as both itemValue and itemLabel, but you're free to choose the attributes that fit your requirements.
Usualy I am doing it with spring tag like this :
<springform:select path="myObjectList" id="selected_company">
<springform:option value="0" label="--- Select One ---"></springform:option>
<springform:options items="${myObjectList}" itemValue="company" itemLabel="company"></springform:options>
</springform:select>
don't forget including the namespace declaration :
xmlns:springform="http://www.springframework.org/tags/form"

struts 2 : Capturing modifications to a guava table (TreeBasedTable) in action

There is an object (ObjectA) which has another object inside (ObjectB). There is a Guava TreeBasedTable inside the Object B. This Table has a string as row-key,column-key and another object "ObjectC" as value. This table has been displayed on the jsp using the <s:iterator/> and <s:textfield/> tags and it is being displayed correctly (the "values" inside the <s:textfield/> are correct but the "names" are not).
Now, the problem arises when the <s:textfield/> is modified. How do we capture the modified values inside ObjectC in the action class?
public class ObjectA implements Serializable {
private Integer attr1;
private List<ObjectB> objB;
//...getters and setters....
public class ObjectB implements Serializable {
private Integer attr11;
private Table<String,String,ObjectC> allPFields;
// ...getters and setters....
public class ObjectC implements Serializable {
private Integer attr111;
public String attr112;
// ...getters and setters....
jsp code:
<!-- language: lang-html -->
<s:iterator value="#objB.allPlainFields.row(#rowKey)" var="fieldMap"
status="fieldStatus">
<li><label><s:property value="#fieldMap.key" /></label><span>
<s:textfield name="<NOT SURE>" value="%{#fieldMap.value.attr12}" />
</span></li>
</s:iterator>
A TreeBasedTable in Guava is similar to a map inside a map, I tried doing allPFields[#outerkey][#innerkey].attr112 but, it didn't work.
The object structure when the screen is displayed with existing values in the database
<!-- language: lang-java -->
objA
objBList ArrayList<E> (id=668)
elementData Object[10] (id=7438)
[0] objB (id=7439)
allPFields TreeBasedTable<R,C,V> (id=7443)
backingMap TreeMap<K,V> (id=8116)
cellSet null
columnComparator NaturalOrdering (id=503)
columnKeySet null
columnMap null
factory TreeBasedTable$Factory<C,V> (id=8117)
rowKeySet null
rowKeySet StandardRowSortedTable$RowKeySortedSet (id=8118)
rowMap StandardRowSortedTable$RowSortedMap (id=8119)
rowMap null
values null
And the "allPFields" looks like the following in action:
{OuterKey1=
{InnerKey1=ObjectC[attr111=31, attr112=Hi there],
InnerKey2=ObjectC[attr111=40, attr112=How are you]
}
}
The "allPFields" value above has been picked up from the IDE console.
As I told you in your other question, I've never used Guava TreeBasedTable;
However, according to the Official Guava Documentation, a
TreeBasedTable , which is essentially backed by a TreeMap<R, TreeMap<C, V>>
and the get method is
V get(Object rowKey, Object columnKey)
Returns the value corresponding to the given row and column keys, or null if no such mapping exists.
In Java it would be:
Object value = objA.getObjB().get(listIndex).getAllPlainFields.get(rowKey, columnKey).getAttr112;
value = "new value";
Then in OGNL you could try something (totally untested) like:
<s:textfield value="%{#fieldMap.value.attr12}"
name="objA.objB[#fieldStatus.index].allPlainFields.get(#rowKey, #fieldMap.Key).attr112" />
P.S: BEWARE OF TYPO... you are using allPlainFields and allPFields together... one of them is wrong, make sure that all the notations point to the right variable name.
P.P.S: I don't know your requirements, but this structure seems a little "over-designed" to me... it definitely does not respect the KISS paradigm :)

ServiceStack ORMLite - Select columns

I recently started working with ServiceStack and its ORMLite framework. I have searched on Google and browsed the source code but couldn't find anything relevent.
Is there any way to select specific columns when executing a query with ORMLite ?
Something like that : Db.First<Model>(q => q.Id == someId, "Column1, Column2")
Unless I missed this feature, I am surprised nobody asked about this before, since this is one the rule of thumbs to optimize your DB transactions.
If you want to specify columns other that the table you need to use SQL as seen in this earlier example
So in your case you could do something like:
Db.First<Model>("SELECT Column1, Column2 FROM AnyTableOrView");
You can also create a partial model that looks at your table by decorating it with the [Alias] attribute, like:
[Alias("AnyTableOrView")]
public class Model {
public int Id { get; set; }
public string Column1 { get; set; }
public string Column2 { get; set; }
}
Then you can do something like:
Db.First<Model>(q => q.Id == someId);
And it will only SELECT + populate fields from the partial model.
I did try this :
Created a Database VIEW (table name and columns are already set)
Created a class named "Event" and matching each fields for that table with a property
(i used [Alias] for table name and for all columns to have nice names)
Wrote access to DB to select 1 record based on it's ID
var dbFactory = new OrmLiteConnectionFactory(
"Data Source=MyDB;User Id=user;Password=pwd", // Connection String
OracleDialect.Provider);
using (var db = dbFactory.OpenDbConnection())
{
var event = db.GetByIdOrDefault<Event>( request.Id );
}
At that point the var 'event' is populated but only the Id field is filled !
all the others fields of the class are not filled (while there are really data in database).
It's the simplest i can do and it does not work. Any ideas ?
(PS : i am using OrmLite for Oracle)
Thanks
I have found the problem.
It was due to an incorrect type matching between field in my class (defined as a string) and the corresponding Oracle Field (that is a DATE).
I replaced the string with datetime and worked like a charm.
So it's working perfectly with a VIEW and that's GREATLY simplify the code.
I had a similar problem, however my solution was different.
I had a int property in my POCO. My query (from Oracle) was returning a null for this property. It caused a exception to be raised and prevented further processing of that row.
The result was a partial populated POCO.
The solution was to change to type to be nullable.
public int? mypropperty

Resources