MyBatis foreach: there is no getter for property error - spring

I'm getting 'there is no getter for property' error while executing foreach loop in mybatis. From the form I am gettin an array of strings (hashtag). In my PostInfoVO, I have a list of string like this:
private List<String> hashtags;
and its getters and setters like this:
public List<String> getHashtags() {
return hashtags;
}
public void setHashtags(List<String> hashtags) {
if (this.items == null)
this.items = new ArrayList<String>();
}
I checked that the list of hashtags is passing data to cotroller by logging postvo.getHashtags().toString().
In my MyBatis file, I have the following foreach loop which is returning 'there is no getter for property hashtag in PostInfoVO.
<![CDATA[
BEGIN
<foreach collection="hashtags" item="hashtag" separator=",">
INSERT INTO TBL_HASHTAG_INFO(post_id, hashtag)
VALUES
((SELECT post_id FROM TBL_POST_INFO ORDER BY post_id DESC LIMIT 1), #{hashtag})
</foreach>;
]]>
END;
List of things I tried:
Removing Begin and end
Taking Insert statement out of foreach loop
Open="(", Close=")"
Any advice would be appreciated! Thank you so much.

There are two problems in your code : your field name is hashtags but you used this.items in setter method and with this setter method you implemented the argument of setter method never assigns to the hashtags(field) ,Edit it as below :
public void setHashtags(List<String> hashtags) {
this.hashtags = hashtags;
}

Related

How to set a Http Session parameter in a JPA named query

I want to set a parameter in a named query (JPA 2.0), so my dataTable would render the respective dataSet. The parameter is obtained remotely and injected in a AbstractFacade class.
I've tried to achieve this through the code above, but it's not working.
Can someone help me?
AbstractFacade (main code):
private String prefDep;
public List<T> findByPrefDep() {
prefDep= FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("xPrefDep");
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
return getEntityManager().createQuery(cq).setParameter("prefDep", prefDep).getResultList();
}
The Entity class (main code):
#NamedQuery(name = "Capacitacao.findByPrefDep", query = "SELECT c FROM Capacitacao c WHERE c.prefDep = :prefDep"),
The AbstractController:
public Collection<T> getItems() {
if (items == null) {
items = this.ejbFacade.findByPrefDep();
}
return items;
}
There is no exception launched, but the dataSet rendered corresponds to a findAll named query.
Thanks in advance.
Your code doesn't use your named query at all. A named query has a name, and your code doesn't use that name anywhere.
Use
getEntityManager().createNamedQuery("Capacitacao.findByPrefDep", Capacitacao.class)
.setParameter("prefDep", prefDep)
.getResultList();
You could have found that yourself by simply reading the EntityManager javadoc.

Use LINQ to select Single from nested collections

I have two classes - MyBaseClass and BaseClassContainer - that are declared like such:
public class MyBaseClass
{
private Guid id;
public Guid ID
{
if (id == Guid.Empty)
{
id = Guid.NewGuid();
}
return id;
}
//...Other Properties omitted for brevity
}
and
public class BaseClassContainer : INotifyPropertyChanged
{
private ObservableCollection<MyBaseClass> baseClasses;
public ObservableCollection<MyBaseClass> BaseClasses
{
//...Omitted for brevity...
}
}
Then in my code I have an ObservableCollection of type BaseClassContainer (BaseClassContainerCollection). What I'm trying to figure out is how can I use LINQ to select a single BaseClassContainer from the ObservableCollection where one of its MyBaseClass.ID matches a specific Guid. The reason I'm using the Single() method is because I know they're all going to be unique.
I've tried the following but it doesn't work:
var result = BaseClassContainerCollection.Single(container => container.BaseClasses.Single(baseClass => baseClass.ID == specificGuid));
I get an error saying: Cannot implicitly convert type 'MyBaseClass' to 'bool'. What am I missing?
Lets break apart your query:
BaseClassContainerCollection.Single(yourPredicate);
Single, as it is used here, basically says "filter BaseClassContainerCollection on this predicate" (a "filter" function that evaluates to true or false for whether or not to include it in the results). Instead of a function that returns true/false, you're saying you want it to evaluate to a MyBaseClass, which doesn't make sense. Your inner call to Single makes sense, because x => x.Id == guid is a function that returns true/false and filters to only those elements that meet the criteria (then states that you know there will only be one of them in the results or else throw an exception).
What you want to do is Select the single MyBaseClass result from the inner query, then call Single on the result (without a predicate) since you know the result should only have one item returned. I believe you're looking for:
BaseClassContainerCollection.Select(container => container.BaseClasses.Single(baseClass => baseClass.ID == specificGuid)).Single();

How to return the result set with columns with Linq

I have a function inside a class that will run a Linq to Entities query (or any type of Linq query actually), and it's gonna return 2 columns in the resultset. I would like to return an object to whoever is calling my function that will allow Intellisense to know what I have returned.
Let me explain. If I have a function like this:
public static IQueryable GetInfo(MyEntityModel oEntityModel)
{
var query =
(from t in oEntityModel.Table1
from u in t.Table2
where t.Status == true &&
u.Status == true
select new
{
t.Column1,
u.Column2
})
return query;
}
What can (should) I put instead of IQueryable so that whoever calls my GetInfo function, will get Intellisense from the resultset, and show that it has a Column1 and Column2?
var linqresult = ClsLinqTeste.GetInfo(oEntityModel);
if (linqresult.Column1 == 1)
{
foreach (var oItem in linqresult)
{
.. do stuff...
}
}
Tks
You cannot return an anonymous type from a function, they are strictly "inline" classes. When you return it, the foreach loop will only be able to interpret the result as an plain object. I guess you could use reflection to query the property names and values, however it seems much more straight forward to define a data transfer type to hold the results.
See this question, and this blog post.
So you could create a simple struct or class:
public class MyDataResult
{
public object Column1 { get; set; }
public object Column2 { get; set; }
}
Then modify your query in the function:
public static IQueryable<MyDataResult> GetInfo(MyEntityModel oEntityModel)
{
var query =
(from t in oEntityModel.Table1
from u in t.Table2
where t.Status == true &&
u.Status == true
select new MyDataResult
{
Column1 = t.Column1,
Column2 = u.Column2
})
return query;
}
Something like that should work. Note that I used "object" for the properties in MyDataResult. I don't know the types of the columns you are returning, you should use the actual types in order to get full intellisense.
You are returning a collection of anonymous types, they will be casted to objects, so when you try to iterate over them, altough they will be your objects (and they will contain your properties) at compile time they will be casted to objects:
foreach (var x in ClsLinqTeste.GetInfo(oEntityModel))
{
//x is an Object
}
You can read more about it here.
If you want to have intellisense, I suggest you create a custom class they will hold your properties and return not an anonymous type (using new {}) but object of your class (new MyClass(prop1, prop2)). You also need to change signature of your method, so it returns IQueryable<YourClass> and not just plain non-generic IQueryable.
As others have said, creating a new type to hold the two columns is usually the best option.
But if, for some reason, you don't want to do that and you are using .Net 4.0, you can use Tuple:
public static IQueryable<Tuple<Column1Type, Column2Type>>
GetInfo(MyEntityModel oEntityModel)
{
return from …
select Tuple.Create(t.Column1, u.Column2);
}
var linqresult = ClsLinqTeste.GetInfo(oEntityModel);
foreach (var oItem in linqresult)
Console.WriteLIne(oItem.Item1, oItem.Item2);
When you return your resultset AsQueryable, the app is already able to give you intellisense, however in your example, you must specify either .FirstOrDefault if you know your collection will only have a single row, or iterate over your collection to get the items from it, like so:
This is what you're doing:
var linqresult = ClsLinqTeste.GetInfo(oEntityModel);
if (linqresult.Column1 == 1)
{
..do stuff...
}
This is how you should do it:
var linqresult = ClsLinqTeste.GetInfo(oEntityModel);
foreach(var item in linqresult)
{
if (item.Column1 == 1)
{
..do stuff...
}
}
You must iterate over linqresult because when you query with link, it returns a result set, even if it just has one column. As with any collection, your data columns aren't available on the whole result set, only with individual items.
If you want to strongly typed enumerate a non-generic IEnumerable (IEnumerable.GetEnumerator() instead of IEnumerable<T>.GetEnumerator<T>()) you can use the Cast<>() extension, like so
var myquery = GetQueryable();
for (var item in myquery.Cast<MyDataType>())
{
// use item.Column1 directly and strongly typed with intellisense
}

How to access data into IQueryable?

I have IQueryable object and I need to take the data inside the IQueryable to put it into Textboxs controls. Is this possible?
I try something like:
public void setdata (IQueryable mydata)
{
textbox1.text = mydata.????
}
Update:
I'm doing this:
public IQueryable getData(String tableName, Hashtable myparams)
{
decimal id = 0;
if (myparams.ContainsKey("id") == true)
id = (decimal)myparams["id"];
Type myType= Type.GetType("ORM_Linq." + tableName + ", ORM_Linq");
return this.GetTable(tableName , "select * from Articu where id_tipo_p = '" + id + "'");
}
public IQueryable<T> GetTable<T>(System.Linq.Expressions.Expression<Func<T, bool>> predicate) where T : class
{
return _datacontext.GetTable<T>().Where(predicate);
}
This returns a {System.Data.Linq.SqlClient.SqlProvider+OneTimeEnumerable1[ORM_Linq.Articu]}`
I don't see any method like you tell me. I see Cast<>, Expression, ToString...
EDIT: Updated based on additional info from your other posts...
Your getData method is returning IQueryable instead of a strongly typed result, which is why you end up casting it. Try changing it to:
public IQueryable<ORM_Linq.Articu> getData(...)
Are you trying to query for "Articu" from different tables?
With the above change in place, your code can be rewritten as follows:
ORM_Linq.Articu result = mydata.SingleOrDefault();
if (result != null)
{
TextBoxCode.Text = result.id.ToString();
TextBoxName.Text = result.descrip;
}
If you have a single result use SingleOrDefault which will return a default value if no results are returned:
var result = mydata.SingleOrDefault();
if (result != null)
{
textbox1.text = result.ProductName; // use the column name
}
else
{
// do something
}
If you have multiple results then loop over them:
foreach (var item in mydata)
{
string name = item.ProductName;
int id = item.ProductId;
// etc..
}
First, you should be using a strongly-typed version of IQueryable. Say that your objects are of type MyObject and that MyObject has a property called Name of type string. Then, first change the parameter mydata to be of type IQueryable<MyObject>:
public void setdata (IQueryable<MyObject> mydata)
Then we can write a body like so to actually get some data out of. Let's say that we just want the first result from the query:
public void setdata (IQueryable<MyObject> mydata) {
MyObject first = mydata.FirstOrDefault();
if(first != null) {
textbox1.Text = first.Name;
}
}
Or, if you want to concatenate all the names:
public void setdata(IQueryable<MyObject> mydata) {
string text = String.Join(", ", mydata.Select(x => x.Name).ToArray());
textbo1.Text = text;
}
Well, as the name suggests, an object implementing IQueryable is... Queryable! You'll need to write a linq query to get at the internal details of your IQueryable object. In your linq query you'll be able to pull out its data and assign bits of it where ever you'd like - like your text box.
Here's a great starting place for learning Linq.
I think you find the same mental struggle when coming from FoxPro and from DataSet. Really nice, powerful string-based capabilities(sql for query, access to tables and columns name) in these worlds are not available, but replaced with a compiled, strongly-typed set of capabilities.
This is very nice if you are statically defining the UI for search and results display against a data source known at compile time. Not so nice if you are trying to build a system which attaches to existing data sources known only at runtime and defined by configuration data.
If you expect only one value just call FirstOrDefault() method.
public void setdata (IQueryable mydata)
{
textbox1.text = mydata.FirstOrDefault().PropertyName;
}

Trouble with a LINQ 'filter' code throwing an error

I've got the following code in my Services project, which is trying to grab a list of posts based on the tag ... just like what we have here at SO (without making this a meta.stackoverflow.com question, with all due respect....)
This service code creates a linq query, passes it to the repository and then returns the result. Nothing too complicated. My LINQ filter method is failing with the following error :-
Method 'Boolean
Contains(System.String)' has no
supported translation to SQL.
I'm not sure how i should be changing my linq filter method :( Here's the code...
public IPagedList<Post> GetPosts(string tag, int index, int pageSize)
{
var query = _postRepository.GetPosts()
.WithMostRecent();
if (!string.IsNullOrEmpty(tag))
{
query = from q in query
.WithTag(tag) // <--- HERE'S THE FILTER
select q;
}
return query.ToPagedListOrNull(index, pageSize);
}
and the Filter method...
public static IQueryable<Post> WithTag(this IQueryable<Post> query,
string tag)
{
// 'TagList' (property) is an IList<string>
return from p in query
where p.TagList.Contains(tag)
select p;
}
Any ideas? I'm at a loss :(
Try with Any:
public static IQueryable<Post> WithTag(this IQueryable<Post> query,
string tag)
{
// 'TagList' (property) is an IList<string>
return from p in query
where p.TagList.Any(t => t == tag)
select p;
}
.
UPDATE (by PureKrome)
Another suggestion by Ahmad (in a comment below). This uses the Contains method so it will return all posts that contain the tag 'Test', eg. Post with Tag 'Testicle' :-
public static IQueryable<Post> WithTag(this IQueryable<Post> query,
string tag)
{
// 'TagList' (property) is an IList<string>
return from p in query
where p.TagList.Any(t => t.Contains(tag))
select p;
}
In WithTag try changing the query to use a List rather than an IList:
return from p in query
let taglist = p.TagList as List<string>
where taglist.Contains(tag)
select p;
Also check out this answer, which is similar to my suggestion: Stack overflow in LINQ to SQL and the Contains keyword

Resources