Giter VIP home page Giter VIP logo

mybatis's People

Watchers

 avatar

mybatis's Issues

Improve automatic column name mapping using camel case conversion

Sorry, I'm new to this but I started investigating this framework today and I'm 
very interested and it's just what I need right now.

What version of the MyBatis are you using?
3.0.1

Please describe the problem.  Unit tests are best!
It's actually a request for feature.
It would be nice that, when auto-mapping column names to pojo properties, 
column names using underscores map according to camel case conventions 
(convention over configuration).

What is the expected output? What do you see instead?
For example, the column 'book_name' should be mapped to the pojo property 
'bookName'. This will make the SQL queries much compact in the XML mapping 
files.

Please provide any additional information below.
I think that FastResultSetHandler.applyAutomaticMappings() can be improved to 
contemplate this, or it could allow some configurable component to be injected 
to provide a custom implementation of column name to property mapping.

If this is something that is accepted, I will be glad to contribute with a 
patch.

Cheers.

Original issue reported on code.google.com by [email protected] on 13 Jun 2010 at 1:54

"javaType=java.sql.ResultSet" required in select definition even though user guide says it is not

What version of the MyBatis are you using?
MyBatis v3.0

Please describe the problem.  Unit tests are best!
When I try to use the following SELECT definition I get a stack trace.

        <select statementType="CALLABLE" id="getUserByAlias"
                parameterType="MyBatisBean" resultType="object">
                call PKG_USER_DATA_SERVICE_MYBATIS.get_user_by_alias (
                #{alias}

,#{retvalUsers,mode=OUT,jdbcType=CURSOR,resultMap=DetailedObjUserVo}
                )
        </select> 


What is the expected output? What do you see instead?
Here is the stack trace:

### Error querying database.  Cause:
org.apache.ibatis.executor.ExecutorException: Type handler was null on
parameter mapping for property retvalUsers.  It was either not specified
and/or could not be found for the javaType / jdbcType combination
specified.
### The error may involve PkgUserDataServiceMapper.getUserByAlias-Inline
### The error occurred while setting parameters
### Cause: org.apache.ibatis.executor.ExecutorException: Type handler
was null on parameter mapping for property retvalUsers.  It was either
not specified and/or could not be found for the javaType / jdbcType
combination specified.
CallStack=org.apache.ibatis.exceptions.PersistenceException:
### Error querying database.  Cause:
org.apache.ibatis.executor.ExecutorException: Type handler was null on
parameter mapping for property retvalUsers.  It was either not specified
and/or could not be found for the javaType / jdbcType combination
specified.
### The error may involve PkgUserDataServiceMapper.getUserByAlias-Inline
### The error occurred while setting parameters
### Cause: org.apache.ibatis.executor.ExecutorException: Type handler
was null on parameter mapping for property retvalUsers.  It was either
not specified and/or could not be found for the javaType / jdbcType
combination specified.
        at
org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFac
tory.java:8)
        at
org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultS
qlSession.java:61)
        at
org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultS
qlSession.java:53)
        at
org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSq
lSession.java:38)
        at
org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:66)
        at
org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:35)
        at $Proxy6.getUserByAlias(Unknown Source)
etc... 


Please provide any additional information below.
The following SELECT definition works correctly -- the only change is to
add "javaType=java.sql.ResultSet".  The manual says this is optional, but
it seems to be mandatory.  Either the doc needs to change or the code needs
a fix.

        <select statementType="CALLABLE" id="getUserByAlias"
                parameterType="MyBatisBean" resultType="object">
                call PKG_USER_DATA_SERVICE_MYBATIS.get_user_by_alias (
                #{alias}

,#{retvalUsers,mode=OUT,jdbcType=CURSOR,javaType=java.sql.ResultSet,resultMap=De
tailedObjUserVo}
                )
        </select> 


Original issue reported on code.google.com by [email protected] on 2 Jun 2010 at 1:04

Update interceptor (plugin) fires for inserts

Reporter:    Eli Kizhnerman

The iBatis plugin does not seem to be resolving the target methods to
intercept properly. An interceptor that is defined to intercept only
updates is also executed on inserts.

I have the following definition:
@Intercepts({@Signature(
        type=Executor.class,
        method="update",
        args={MappedStatement.class,Object.class})})
public class UpdateInterceptor implements Interceptor {
...
}

In Plugin.invoke you have the following code:

      Set<Method> methods = signatureMap.get(method.getDeclaringClass());
      if (methods != null && methods.contains(method)) {
        return interceptor.intercept(new Invocation(target, method, args));
      }

DefaultSqlSession.insert internally calls an update method:

  public int insert(String statement, Object parameter) {
    return update(statement, parameter);
  }

I suspect that the Method that is being passed to plugin.invoke is actually
the update method and therefore the interceptor is executed. 

Original issue reported on code.google.com by [email protected] on 17 May 2010 at 1:39

Clarify error message for nullable parameters

Reporter:    Gili

I am getting an error message:

   "JDBC requires that the JdbcType must be specified for all nullable
parameters [...] The error may involve <mapper name>-Inline". Granted,
telling me the mapper name is useful but I believe we can improve this
error message in two regards:

# I mistakenly read "nullable parameters" as "nullable columns" and wasted
time looking for problems in my database schema. I wonder if others have
made a similar mistake...? Is it possible to rephrase this as follows?
"Mapper methods cannot accept null arguments without a properly configured
JdbcType. Either specify a JdbcType or refrain from passing in null."

# I noticed that when this exception is thrown iBatis has quite a bit more
information available to it. Is it possible to add the following
information to the error message?

Prepared statement: "SELECT * FROM animals WHERE name = ? AND age > ?",
parameter #2 was null

   This would enable me to track down exactly which parameter was equal to
null.

Original issue reported on code.google.com by [email protected] on 17 May 2010 at 1:30

ManagedTransaction closing Connection

Mybatis 3.0.2, per revision 1926, changed the ManagedTransaction close method 
so that it actually closes the Connection. Why was this changed? 
ManagedTransaction implies that something else is handling commit and 
rollback. Doesn't that also imply that something else is handling close too?

There is an if check for a null Connection. But, there's no way from the 
public API to have a null Connection. If you call SqlSession session = 
sessionFactory.openSession(executorType, (Connection) null), a 
NullPointerException is thrown.

Original issue reported on code.google.com by [email protected] on 27 May 2010 at 2:18

Mapper url under MS Windows doesn't work

What version of the MyBatis are you using?
MyBatis 3.0.1 bundle

Please describe the problem.  Unit tests are best!
According to the user guide i am able to use file path instead of resource:
// Using classpath relative resources 
<mappers> 
    <mapper resource="org/mybatis/builder/AuthorMapper.xml"/> 
</mappers> 

// Using url fully qualified paths 
<mappers> 
    <mapper url="file:///var/sqlmaps/AuthorMapper.xml"/> 
</mappers>

in my project I'm trying to put my mapper xml "outside" the project and i'm 
doing this:
<mapper url="file://D:/Mappers/AuthorMapper.xml" />

The output of my log4j console:
### Error building SqlSession.
### The error may exist in file://D:/Mappers/ComponentMapper1.xml
### Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper 
Configuration. Cause: java.net.UnknownHostException: D

What is the expected output? What do you see instead?
No error :)

Please provide any additional information below.


Original issue reported on code.google.com by kospiotr on 8 Jun 2010 at 1:05

Add message to warn about missing column name in nested select

Reporter:    viv

what I am seeing is the nested select is not getting executed. To make it
simpler, I created a simple prototype. I know in this example I don't need
to create a separate select, but wondering why its not working. Here are
the details

POJOs
public class Car
{
private int carId ;
private String name ;

private List<Parts> carParts ;
}


public class Parts
{
private int partId;
private String name ;
}

==============
Mapper

<resultMap id="carResult" type="Car">
<id property="carId" column="id"/>
<result property="name" column="name"/>
<collection property="carParts" javaType="ArrayList" ofType="Parts"
select="getCarPartInfo"/>
</resultMap>

<select id="getCarsInfo" resultMap="carResult">
SELECT car_id as "id", name
FROM Car where car_id=1
</select>

<select id="getCarPartInfo" resultType="Parts">
SELECT part_id as "partId", name
FROM Parts where car_id=1
</select>
==========
Tables
======


mysql> select * from car;
+--------+------+
| car_id | name |
+--------+------+
| 1 | Audi |
+--------+------+
1 row in set (0.00 sec)


mysql> select * from Parts;
+---------+------------+--------+
| part_id | name | car_id |
+---------+------------+--------+
| 100 | door | 1 |
| 101 | windshield | 1 |
| 102 | Brakes | 1 |
+---------+------------+--------+
3 rows in set (0.00 sec)


=========================

Unit Test

public void testGetCarInfo() {
List<Car> list = repository.getCarsInfo();
for (Iterator<Car> carIter = list.iterator();carIter.hasNext();) {
Car d = carIter.next();
logger.debug("Car id " + d.getCarId() + " name " + d.getName());
List<Parts> dPartList = d.getCarParts();
if (dPartList!=null) {
logger.debug(" car Part iterator is not null " + dPartList.size());
} else {
logger.debug(" car Part List is null " );
}

}

assertNotNull("At least one device must exist", list);
}



Unit Test Result

2010-04-07 11:27:11,576 DEBUG [iBatisImplTest] Car id 1 name Audi
2010-04-07 11:27:11,577 DEBUG [iBatisImplTest] car Part List is null


As you can see the result does not contain the Parts List, the Collection
is not getting set. It does not throw any warning, error or exception
simply returns empty list.

The reason was because column attribute was missing from Collection. when I
added <collection property="carParts" column="id" javaType="ArrayList"
ofType="Parts" select="getCarPartInfo"/> it worked fine.
As per Clinton, the missing column must have been caught.

Original issue reported on code.google.com by [email protected] on 17 May 2010 at 1:28

'script_char_set' is applied incorrectly for migration scripts

What version of the MyBatis are you using?
Migration 3.0.1

Please describe the problem.  Unit tests are best!

Currently, 'script_char_set' is applied in ScriptRunner#executeStatement() 
method with the following line, but it doesn't work as intended.

new String(command.getBytes(), characterSetName);

The character set must be specified when reading the file.
In BootstrapCommand, for example, ScriptRunner#runScript() is currently called 
as follows:

runner.runScript(new MigrationReader(new FileReader(bootstrap), false, 
environmentProperties()));

but it should be something like:

runner.runScript(
  new MigrationReader(
    new InputStreamReader(
      new FileInputStream(bootstrap),
      environmentProperties().getProperty("script_char_set")
    ), 
    false, environmentProperties()
  )
);

The same goes for other commands as well.

Original issue reported on code.google.com by [email protected] on 18 Jun 2010 at 8:51

Provide a way for not creating items from nested ResultMaps when some columns return null (a.k.a. @notNullColumn)

What version of the MyBatis are you using? 3.0.1 GA

The problem is that using eager fecthing of nested elements, sometimes it is 
necessary to do LEFT JOINs that create extra rows that one does not want to 
take into account so empty objcecs are not created. 

This feature was already present in Ibatis 2 and one can find more information 
and examples at the following issues:
Ibatis .NET: https://issues.apache.org/jira/browse/IBATISNET-206
Ibatis Java: https://issues.apache.org/jira/browse/IBATIS-375

In order to keep compatibility, one would suggest using the same notNullColumn 
attribute for the result element, unless there is a specific reason.

Original issue reported on code.google.com by [email protected] on 8 Jun 2010 at 7:52

New typehandler implementation is not called during select statment.

Reporter:    István Tóth
Affects Version/s:       3.0 Beta 10 

Hi!

I have created a new type handler called GregorianCalendarTypeHandler. This
type handler is used to convert java type: java.util.GregorianCalendar to
jdbc type: DATE and vice verse. The code is the following:

import java.sql.CallableStatement;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Locale;

import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;

public class GregorianCalendarTypeHandler implements TypeHandler
{
public Object getResult(final ResultSet rs, final String columnName) throws
SQLException
{
return this.createCalendar(rs.getObject(columnName));
}

public Object getResult(final CallableStatement cs, final int columnIndex)
throws SQLException
{
return this.createCalendar(cs.getObject(columnIndex));
}

public void setParameter(final PreparedStatement ps, final int i, final
Object parameter, final JdbcType jdbcType) throws SQLException
{
final Calendar calendar = (Calendar) parameter;
if (JdbcType.DATE.equals(jdbcType))
{
ps.setDate(i, new Date(calendar.getTimeInMillis()), calendar);
}
else if (JdbcType.TIME.equals(jdbcType))
{
ps.setTime(i, new Time(calendar.getTimeInMillis()), calendar);
}
else if (JdbcType.TIMESTAMP.equals(jdbcType))
{
ps.setTimestamp(i, new Timestamp(calendar.getTimeInMillis()), calendar);
}
else
{
throw new SQLException("The " + this.getClass() + " typehandler can handle
only DATE, TIME, TIMESTAMP types not: " + jdbcType);
}
}

protected Calendar createCalendar(final Object sqlDate) throws SQLException
{
if (!(sqlDate instanceof java.util.Date))
{
throw new SQLException("The following object is not an instance of the
java.util.Date: " + sqlDate);
}

final Locale locale = Get it from somewhere;
final TimeZone timeZone = Get it from somewhere;

final GregorianCalendar calendar = new GregorianCalendar(locale,timezone);

calendar.setTime((java.util.Date) sqlDate);

return calendar;
}
}

As you can see below, I have registered this new type handler into my
config.xml:

<typeHandlers>
<typeHandler javaType="java.util.GregorianCalendar" jdbcType="DATE"
handler="somepackage.GregorianCalendarTypeHandler"/>
</typeHandlers>

I'm facing with the following problem:

When I run an insert statement anything is fine, the GregorianCalendar is
converted to date with the type handler's setParameter method and the row
is inserted in the database.

The problem is with the reading. When a select statement is executed the
Date value from the database is queried but it is not set to the POJO's
proper property.

I had done some investigation and debug and figured out the problem is with
the TypeHandlerRegistry#hasTypeHandler(Class) method. This method calls the
other hasTypeHandler(Class, JDBCType) but with null value as jdbc type. The
"TYPE_HANDLER_MAP" map member contains my handler object with the key
"DATE", but the method tries to get a handler with the key null!

It is also strange that the other built in type handlers are stored into
this member with null as key.

Please fix this error (if this is a bug, or I don't know I'm doing
something wrong?) and help me. If you need more info about this issue
please let me know.

Regards, István.

Original issue reported on code.google.com by [email protected] on 23 May 2010 at 1:36

how to print the msg that Ibatis's sql statement in the jetty server.

What version of the MyBatis are you using?
    ibatis 2.3.4

Please describe the problem.  Unit tests are best!
    I want to print the sql statement in jetty .

What is the expected output? What do you see instead?


Please provide any additional information below.
  I hava a log4j config file.My Application can print it in tomcat ,but cant't print it in jetty.

Original issue reported on code.google.com by [email protected] on 13 Jun 2010 at 1:50

Base class for enum TypeHandlers using ordinal value for persistence

Reporter:    Jan Novotný

In some cases it would be useful to have base class for enum TypeHandlers,
that allow to store enumerations to the database by their ordinal() value.
Code might look like this:

/**
 * This class converts enumeration type into the database form by ordinal
value (and back again).
 */
public abstract class EnumOrdinalTypeHandler extends BaseTypeHandler {
private final Class type;
private final Method values;

protected EnumOrdinalTypeHandler(Class type) {
this.type = type;
try {
this.values = type.getDeclaredMethod("values");
} catch(Exception ex) {
throw new IllegalArgumentException("Class " + type.getSimpleName() + " is
not an enumeration class.", ex);
}
}

@Override
public void setNonNullParameter(PreparedStatement ps, int i, Object
parameter, JdbcType jdbcType) throws SQLException {
ps.setInt(i, ((Enum)parameter).ordinal());
}

@Override
public Object getNullableResult(ResultSet rs, String columnName) throws
SQLException {
int i = rs.getInt(columnName);
if(rs.wasNull()) {
return null;
} else {
try {
Object[] enums = (Object[])values.invoke(null);
return enums[i];
} catch (Exception ex) {
throw new IllegalArgumentException(
"Cannot convert " + i + " to " + type.getSimpleName() + " by ordinal
value.", ex
);
}
}
}

@Override
public Object getNullableResult(CallableStatement cs, int columnIndex)
throws SQLException {
int i = cs.getInt(columnIndex);
if(cs.wasNull()) {
return null;
} else {
try {
Object[] enums = (Object[])values.invoke(null);
return enums[i];
} catch (Exception ex) {
throw new IllegalArgumentException(
"Cannot convert " + i + " to " + type.getSimpleName() + " by ordinal
value.", ex
);
}
}
}

}

Code is tested and functional.

Original issue reported on code.google.com by [email protected] on 17 May 2010 at 1:35

Inability to easily extend the Configuration class while using XML mapper files

What version of the MyBatis are you using?
V3.0

Please describe the problem.  Unit tests are best!
It is not possible to easily extend the Configuration class and also use
XML for mapper configurations.  The SqlSessionFactoryBuilder class only
allows you to pass in the Configuration instance when you aren't also
passing in a Reader instance.  The config DTD doesn't support specifying
the Configuration class to use, so you can either use XML to configure an
instance of the standard Configuration class *or* you can use your own
subclass of Configuration without using XML - but you can't use your own
subclass *with* XML.  Given the limits to Java annotations as discussed
elsewhere, it seems necessary to be able to use XML config files while
overriding the Configuration class. 



What is the expected output? What do you see instead?


Please provide any additional information below.
I think making the following change to the XMLConfigBuilder class to allow
passing in an instance of both Reader and Configuration would do it.

Change these 2 lines:

public XMLConfigBuilder(Reader reader, String environment, Properties props) {
    super(new Configuration());

To these 5 lines:

public XMLConfigBuilder(Reader reader, String environment, Properties props) {
    this(reader, environment, props, null);
}
public XMLConfigBuilder(Reader reader, String environment, Properties
props, Configuration configuration) {
   super(configuration != null ? configuration : new Configuration()); 

Then a new constructor on SQLSessionFactoryBuilder to call the new
constructor in XMLConfigBuilder would be necessary, and the documentation
will require a change to document the new SQLSessionFactoryBuilder constructor.

Amending the config DTD to support specifying the Configuration class name
might also be a possibility.


Original issue reported on code.google.com by [email protected] on 2 Jun 2010 at 12:58

  • Merged into: #22

Improve error message when Mapper refers to non-existent variables

Reporter:    Gili

I had this code:

   @Select("SELECT value FROM seat_properties WHERE seat = #{seat} AND key
= #{key}")
   String get(short seat, String key);

I wrongly assumed that iBatis would grab the parameter names from the
method declaration. Instead, it names the parameters #{1}, #{2}, etc. When
iBatis tried invoking this method, it couldn't find #{seat} so it assigned
it a null value and failed with the aforementioned error message. I had to
use the @Param annotation to fix this:

   @Select("SELECT value FROM seat_properties WHERE seat = #{seat} AND key
= #{key}")
   String get(@Param("seat") short seat, @Param("key") String key);

Shouldn't iBatis fail-fast when the parameter it is looking up ("seat" in
my case) is missing, as opposed to assigning it a null value? A nice error
message would be "Could not find parameter #{seat}. The following
parameters are defined: #{1}, #{2}." I would have caught on fairly quickly
with that error message.

Original issue reported on code.google.com by [email protected] on 17 May 2010 at 1:29

PeerListResultTest doesn't use offline entity resolver like other tests and may fail behind a firewall proxy

MyBatis v3.0.1.  The test class com.submitted.resultmap.PeerListResultTest 
doesn't use an offline entity resolver like other tests, and this can cause 
problems behind a firewall proxy.  The solution is to change lines 89 and 90 in 
PeerListResultTest.java from this:

sqlMapClient = SqlMapClientBuilder
            .buildSqlMapClient(reader);

to this:

sqlMapClient = SqlMapClientBuilder
            .buildSqlMapClient(reader, null);

Without this change, when behind a firewall proxy and despite Eclipse and Maven 
being configured properly to use that proxy, the following error results and 
causes the test case to fail:

org.apache.ibatis.parsing.ParsingException: Error parsing XML.  Cause: 
java.net.ConnectException: Connection timed out: connect
    at com.ibatis.common.util.NodeEventParser.parse(NodeEventParser.java:57)
    at com.ibatis.sqlmap.engine.builder.XmlSqlMapConfigParser.parse(XmlSqlMapConfigParser.java:49)
    at com.ibatis.sqlmap.client.SqlMapClientBuilder.buildSqlMapClient(SqlMapClientBuilder.java:49)
    at com.submitted.resultmap.PeerListResultTest.setUp(PeerListResultTest.java:90)
    at junit.framework.TestCase.runBare(TestCase.java:132)
    at junit.framework.TestResult$1.protect(TestResult.java:110)
    at junit.framework.TestResult.runProtected(TestResult.java:128)
    at junit.framework.TestResult.run(TestResult.java:113)
    at junit.framework.TestCase.run(TestCase.java:124)
    at junit.framework.TestSuite.runTest(TestSuite.java:232)
    at junit.framework.TestSuite.run(TestSuite.java:227)
    at org.junit.internal.runners.OldTestClassRunner.run(OldTestClassRunner.java:76)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:45)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Caused by: java.net.ConnectException: Connection timed out: connect
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:333)
    at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:195)
    at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:182)
    at java.net.Socket.connect(Socket.java:519)
    at java.net.Socket.connect(Socket.java:469)
    at sun.net.NetworkClient.doConnect(NetworkClient.java:157)
    at sun.net.www.http.HttpClient.openServer(HttpClient.java:394)
    at sun.net.www.http.HttpClient.openServer(HttpClient.java:529)
    at sun.net.www.http.HttpClient.<init>(HttpClient.java:233)
    at sun.net.www.http.HttpClient.New(HttpClient.java:306)
    at sun.net.www.http.HttpClient.New(HttpClient.java:323)
    at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:788)
    at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:729)
    at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:654)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:977)
    at java.net.URL.openStream(URL.java:1009)
    at org.apache.xerces.impl.XMLEntityManager.startEntity(XMLEntityManager.java:796)
    at org.apache.xerces.impl.XMLEntityManager.startDTDEntity(XMLEntityManager.java:756)
    at org.apache.xerces.impl.XMLDTDScannerImpl.setInputSource(XMLDTDScannerImpl.java:267)
    at org.apache.xerces.impl.XMLDocumentScannerImpl$DTDDispatcher.dispatch(XMLDocumentScannerImpl.java:826)
    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:333)
    at org.apache.xerces.parsers.DTDConfiguration.parse(DTDConfiguration.java:524)
    at org.apache.xerces.parsers.DTDConfiguration.parse(DTDConfiguration.java:580)
    at org.apache.xerces.parsers.XMLParser.parse(XMLParser.java:152)
    at org.apache.xerces.parsers.DOMParser.parse(DOMParser.java:253)
    at org.apache.xerces.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:201)
    at com.ibatis.common.util.NodeEventParser.createDocument(NodeEventParser.java:155)
    at com.ibatis.common.util.NodeEventParser.parse(NodeEventParser.java:53)
    ... 17 more


Original issue reported on code.google.com by [email protected] on 9 Jun 2010 at 6:33

Exception while input null array parameter

What version of the MyBatis are you using?
3.0.1

Please describe the problem.  Unit tests are best!

org.apache.ibatis.exceptions.PersistenceException: 
### Error updating database.  Cause: org.apache.ibatis.type.TypeException: 
Error setting null parameter.  Most JDBC drivers require that the JdbcType must 
be specified for all nullable parameters. Cause: java.sql.SQLException: 
无效的列类型: 1111
### The error may involve ewell.ipphone.service.entity.addExpertResource-Inline
### The error occurred while setting parameters
### Cause: org.apache.ibatis.type.TypeException: Error setting null parameter.  
Most JDBC drivers require that the JdbcType must be specified for all nullable 
parameters. Cause: java.sql.SQLException: 无效的列类型: 1111
    at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:8)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:100)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:87)
    at ewell.ipphone.service.entity.IBatisDAO.insert(IBatisDAO.java:27)
    at ewell.ipphone.service.entity.sys.users.ExpertResourceServiceImpl.add(ExpertResourceServiceImpl.java:57)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
    at ewell.ipphone.service.entity.TransactionInterceptor.invoke(TransactionInterceptor.java:32)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
    at $Proxy9.add(Unknown Source)
    at ewell.ipphone.service.unittest.ExpertResourceServiceTest.testAdd(ExpertResourceServiceTest.java:52)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

What is the expected output? What do you see instead?

no error. Actually it output exception

Please provide any additional information below.


Original issue reported on code.google.com by [email protected] on 12 Jun 2010 at 12:08

Add built-in multi DB vendor support

Reporter:    Russ Jackson

The feature in iBatis 3 to use getMapper() to obtain a dynamic
implementation of the DAO interface is extremely cool. However, there is
one serious shortcoming - mapped statement implementations that are DB
product specific/variant are not currently supported by this.

For example, say I have a couple of vendor-specific SELECT statements that
represent the same query. The way one can address this situation is
described in the following blog posting by Jeff Hair (who happens to be a
colleague of mine): http://jshair.blogspot.com/ (scroll down to the iBatis
entry)
As you can see, Jeff describes adding a base DAO class that extends
Spring's SqlMapClientDaoSupport. Inside this base class the
checkMappedStatement() method manipulates the statement name to be DB
product specific (based on the db metadata obtained from the db connection)
and attempts to look up a mapped statement based on that name. If that
fails, the original/default name is used to find the mapped statement.

What I have done is basically push a variant of the implementation that
Jeff describes down into your DefaultSqlSession class to provide the
capability for your dynamic mapper methods to execute overloaded,
vendor-specific SQL statements - all transparent to the DAO client. (see
attached - I put the new work just after your constructor)

I built the iBatis project locally and deployed it to my environment and it
seems to work fine. There is one kink that still needs to be worked out - I
did not put this mapped SQL overload into your
MapperMethod.determineCommandType() method and as a result, the xml mapper
still requires that a non-db-specific SELECT statement exists. For example,
consider the following: For argument's sake I have getAll-Oracle and
getAll-HSQL mapped SELECT statements representing some SELECT statements
that are, for one reason or another, vendor-specific. But, I also have to
provide an undesired getAll implementation to prevent an exception in the
determineCommandType() method.

<mapper namespace="com.acme.banking.persistence.dao.ITransactionTypeDao">
<resultMap id="get-transactionType-result"
type="TransactionType">
<result property="code" column="code"/>
<result property="title" column="title"/>
</resultMap>
<select id="getAll-HSQL" resultType="TransactionType">
SELECT code, title
FROM transaction_type
</select>
<select id="getAll-Oracle" resultType="TransactionType">
SELECT title, code
FROM transaction_type
</select>
<select id="getAll" resultType="TransactionType">
SELECT title, code
FROM transaction_type
</select>
</mapper>

It would be great if you could eliminate this problem/requirement if you
decide to use this implementation/idea.

Thanks again.

Original issue reported on code.google.com by [email protected] on 17 May 2010 at 1:42

a new @ResultMap annotation to allow for @Select annotations on methods in mapper interfaces to use ResultMaps declared in XML files

Reporter:  Travis Hein   

Would it be possible to create a new annotation (or does one exist already
and I just have not found it yet), where I can specify that @Select results
should be a <resultMap> that exists in the mapper XML file ?


For example,

Consider a "country" table,

[code]
CREATE TABLE COUNTRY
(
   ID bigint PRIMARY KEY NOT NULL,
   CODE varchar(2) NOT NULL,
   ISO_CODE varchar(3) NOT NULL,
   NAME varchar(2147483647),
   COUNTRY_CODE varchar(10),
   ACTIVE boolean DEFAULT TRUE NOT NULL
);
[/code]

And the java Bean,

[code]
public class Country {
  Long id;
  String code; // 2 digit ISO country code
  String isoCode; // 3 digit ISO country code
  String name; // string name
  String countryCode; // the telephone dialing prefix (e.g. +1)
  boolean active = true;

  // and all the get() set() methods for these bean properties
}
[/code]


And then the mapper interface,

[code]
public interface CountryDAO {

  /**
  * Selects all country entries.
  * Though it appears when we use the annotations, we need to specify the
results every time ?
  */
  @Select( value = { "select * from country where active = true" })
  @Results(value = {
      @Result(property="id"),
      @Result(property="code"),
      @Result(property="isoCode", column="iso_code"),
      @Result(property="name", column="name"),
      @Result(property="countryCode", column="country_code"),
      @Result(property="active", column="active")
  })
  List<Country> getAllActive();

  // TODO: all these methods would also be select queries, where I would
want the same results map as above
  Country getById(Long id);
  Country getByCode(String code);
  Country getByIsoCode(String isoCode);
}
[/code]


Where, instead of the @Results annotation, which would need to be
duplicated with its nested @Result annotations on every select method that
I want to return the same mapping, what I would wish to have would be
something like a

@ResultMap(value="myMapperID")

annotation, where the myMapperID would be the ID of a <resultMap> I have
declared in the mapper's xml file that will be included by the
SqlMapConfig.xml (which I have anyway to bind to this mapper interface, and
also because I have some more complex queries declared in the xml mapper
file too).

Where in this example, I already have a

[code]
<mapper namespace="CountryDAO">

<resultMap type="Country" id="countryResult">
<result property="id" column="id"/>
<result property="code" column="code"/>
<result property="isoCode" column="iso_code"/>
<result property="name" column="name"/>
<result property="countryCode" column="country_code"/>
<result property="active" column="active"/>
</resultMap>
[/code]


So this wishful @ResultMap annotation would then make the mapper interface
look like:

[code]
public interface CountryDAO {

  @Select( value = { "select * from country where active = true" })
  @ResultMap(value = "countryResult")
  List<Country> getAllActive();


  // and now other things that want to select into this map can do so,
re-using the single map declaration
  // that is referenced in the xml.

  @Select( value = { "select * from country where id = #{id} })
  @ResultMap(value = "countryResult")
  Country getById(Long id);


  @Select( value = { "select * from country where code = #{code} })
  @ResultMap(value = "countryResult")
  Country getByCode(String code);

  @Select( value = { "select * from country where isoCode = #{isoCode} })
  @ResultMap(value = "countryResult")
  Country getByIsoCode(String isoCode);
}
[/code]


I think having something like this @ResultMap annotation would be a good
thing to have, what do you think? 

Original issue reported on code.google.com by [email protected] on 17 May 2010 at 1:24

Support case insensitive Mapper / Mapper.xml relationships and duplicate detection

Reporter:    Daniel Stanciu

I am getting an exception when I try to call
SqlSessionFactoryBuilder.build. The exception is:
Exception in thread "main" org.apache.ibatis.exceptions.IbatisException:
### Error building SqlSession.
### The error may exist in my/test/DbMapper.xml
### The error occurred while processing mapper_resultMap[TestResult]
### Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL
Mapper Configuration. Cause: java.lang.RuntimeException: Error parsing
Mapper XML. Cause: java.lang.IllegalArgumentException: Result Maps
collection already contains value for my.test.DbMapper.TestResult
at
org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.jav
a:8)
at
org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilde
r.java:32)
at
org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilde
r.java:23)
at
amdocs.pv.configurationtool.client.PvConfigurationPlugin.login(PvConfigurationPl
ugin.java:376)
at
amdocs.pv.configurationtool.client.PvConfigurationPlugin.main(PvConfigurationPlu
gin.java:353)
Caused by: org.apache.ibatis.builder.BuilderException: Error parsing SQL
Mapper Configuration. Cause: java.lang.RuntimeException: Error parsing
Mapper XML. Cause: java.lang.IllegalArgumentException: Result Maps
collection already contains value for my.test.DbMapper.TestResult
at
org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration(XMLConfigBuild
er.java:71)
at
org.apache.ibatis.builder.xml.XMLConfigBuilder.parse(XMLConfigBuilder.java:55)
at
org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilde
r.java:29)
... 3 more
Caused by: java.lang.RuntimeException: Error parsing Mapper XML. Cause:
java.lang.IllegalArgumentException: Result Maps collection already contains
value for my.test.DbMapper.TestResult
at
org.apache.ibatis.builder.xml.XMLMapperBuilder.configurationElement(XMLMapperBui
lder.java:59)
at
org.apache.ibatis.builder.xml.XMLMapperBuilder.parse(XMLMapperBuilder.java:39)
at
org.apache.ibatis.builder.annotation.MapperAnnotationBuilder.loadXmlResource(Map
perAnnotationBuilder.java:71)
at
org.apache.ibatis.builder.annotation.MapperAnnotationBuilder.parse(MapperAnnotat
ionBuilder.java:49)
at org.apache.ibatis.binding.MapperRegistry.addMapper(MapperRegistry.java:43)
at org.apache.ibatis.session.Configuration.addMapper(Configuration.java:354)
at
org.apache.ibatis.builder.xml.XMLMapperBuilder.bindMapperForNamespace(XMLMapperB
uilder.java:234)
at
org.apache.ibatis.builder.xml.XMLMapperBuilder.parse(XMLMapperBuilder.java:40)
at
org.apache.ibatis.builder.xml.XMLConfigBuilder.mapperElement(XMLConfigBuilder.ja
va:247)
at
org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration(XMLConfigBuild
er.java:69)
... 5 more
Caused by: java.lang.IllegalArgumentException: Result Maps collection
already contains value for my.test.DbMapper.TestResult
at
org.apache.ibatis.session.Configuration$StrictMap.put(Configuration.java:395)
at
org.apache.ibatis.session.Configuration$StrictMap.put(Configuration.java:370)
at org.apache.ibatis.session.Configuration.addResultMap(Configuration.java:294)
at
org.apache.ibatis.builder.MapperBuilderAssistant.addResultMap(MapperBuilderAssis
tant.java:128)
at
org.apache.ibatis.builder.xml.XMLMapperBuilder.resultMapElement(XMLMapperBuilder
.java:148)
at
org.apache.ibatis.builder.xml.XMLMapperBuilder.resultMapElement(XMLMapperBuilder
.java:118)
at
org.apache.ibatis.builder.xml.XMLMapperBuilder.resultMapElements(XMLMapperBuilde
r.java:113)
at
org.apache.ibatis.builder.xml.XMLMapperBuilder.configurationElement(XMLMapperBui
lder.java:55)
... 14 more

The configuration files I have are:
config2.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
  PUBLIC "-//ibatis.apache.orgg//DTD Config 3.0//EN"
  "http://ibatis.apache.org/dtd/ibatis-3-config.dtd">

<configuration>
<typeAliases>
<typeAlias alias="Label" type="java.awt.Label" />
</typeAliases>

<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="oracle.jdbc.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@${server}:${port}:${instance}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>

<mappers>
<mapper resource="my/test/DBMapper.xml"/>
</mappers>
</configuration>

DBMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN"
  "http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd">
<mapper namespace="my.test.DbMapper">
<resultMap id="TestResult" type="Label">
<result property="text" column="test"/>
</resultMap>

<select id="selectTest" resultMap="TestResult">
select * from test
</select>
</mapper>

I found out that the problem reproduces only when I have the following
interface defined:
package my.test;

public interface DbMapper {
public java.awt.Label selectTest();
}

Somehow, it parses the xml again and it gives the exception. 

Original issue reported on code.google.com by [email protected] on 17 May 2010 at 1:30

Error when lazy loading a preloaded common property

Let's say we have a child how has a father and a grandfather property that are 
lazy loaded.
The father also have a grandfather property that is lazy loaded.
If we load the grandfather and then the child - the father is not loaded - this 
results in a ConcurrentModificationException.
To obtain the exception, the statements must be executed in the same SqlSession 
instance.
I've included a simple test case showing the problem and showing that if the 
father is loaded before the child, the problem disappear.

Here is the stack trace obtained.
org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: java.util.ConcurrentModificationException
### The error may involve 
org.apache.ibatis.submitted.lazyload_common_property.FatherMapper.selectById-Inl
ine
### The error occurred while setting parameters
### Cause: java.util.ConcurrentModificationException
    at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:8)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:61)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:53)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:38)
    at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:66)
    at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:35)
    at $Proxy6.selectById(Unknown Source)
    at org.apache.ibatis.submitted.lazyload_common_property.CommonPropertyLazyLoadError.testLazyLoadSkipFirstAncestor(CommonPropertyLazyLoadError.java:95)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.junit.internal.runners.TestMethodRunner.executeMethodBody(TestMethodRunner.java:99)
    at org.junit.internal.runners.TestMethodRunner.runUnprotected(TestMethodRunner.java:81)
    at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34)
    at org.junit.internal.runners.TestMethodRunner.runMethod(TestMethodRunner.java:75)
    at org.junit.internal.runners.TestMethodRunner.run(TestMethodRunner.java:45)
    at org.junit.internal.runners.TestClassMethodsRunner.invokeTestMethod(TestClassMethodsRunner.java:66)
    at org.junit.internal.runners.TestClassMethodsRunner.run(TestClassMethodsRunner.java:35)
    at org.junit.internal.runners.TestClassRunner$1.runUnprotected(TestClassRunner.java:42)
    at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34)
    at org.junit.internal.runners.TestClassRunner.run(TestClassRunner.java:52)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.util.ConcurrentModificationException
    at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
    at java.util.AbstractList$Itr.next(AbstractList.java:343)
    at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:104)
    at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:72)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:59)
    ... 26 more



Original issue reported on code.google.com by [email protected] on 18 Jun 2010 at 3:31

Attachments:

lazy loading is of no effect on debug mode

Reporter:    huangwei

Lazy loading is of no effect on debug mode of IntelliJ IDEA(version 8.1.3)
When I excute the code in debug mode in IntelliJ IDEA, it would also run
the nested select sql.
setting:
   <settings>
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>
    </settings>
sqlmapper:
<resultMap id="selectItemResult" type="org.apache.ibatis.example.Item">
        <id property="itemId" column="itemId"/>
        <result property="productId" column="productId"/>
        <association property="inventory" column="itemid"
select="selectInventory">
        </association>
    </resultMap>
<select id="selectItem" parameterType="string" resultMap="selectItemResult">
        select * from item where itemid = #{itemid}
</select>
<select id="selectInventory" parameterType="string"
resultType="org.apache.ibatis.example.Inventory">
        select * from inventory where itemid = #{itemid}
  </select>
test code:
Item item = (Item)
session.selectOne("org.apache.ibatis.example.selectItem", "EST-1");
System.out.println(item.getItemId());

If I excute it in running mode, it is ok.
Please help.

Original issue reported on code.google.com by [email protected] on 17 May 2010 at 1:26

circular reference in resultMap for join select - StackOverflowError

Reporter:    Libor Tomáš

I created circular reference (feeGroup.fees -> fee.feeGroup ->
feeGroup.fees) in resultMap for join select but I got StackOverflowError.
It seems that circular references work only for lazy loading?

--------------------------------------------------------------------------------
--------

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//ibatis.apache.org//DTD iBatis Mapper 3.0 //EN"
"http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd">
<mapper namespace="mapper.FeeGroup">

<resultMap id="map" type="model.FeeGroup">
<id property="id" column="FEE_GROUPS_1" />
<result property="name" column="FEE_GROUPS_2" />
<result property="valid" column="FEE_GROUPS_3" />
<collection property="fees" resultMap="mapper.Fee.map" />
</resultMap>

<select id="getByWithTables" parameterType="java.util.Map" resultMap="map">
select
FEES.ID as FEES_1,
FEES.ID_FEE_GROUP as FEES_2,
FEES.PRICE_SELLER as FEES_3,
FEES.PRICE_CALL_CENTRUM as FEES_4,
FEES.PRICE_OPERATOR as FEES_5,
FEES.VALID_FROM as FEES_6,
FEES.VALID_TO as FEES_7,
FEES.MAX_OPERATOR_MEETING as FEES_8,
FEE_GROUPS.ID as FEE_GROUPS_1,
FEE_GROUPS.NAME as FEE_GROUPS_2,
FEE_GROUPS.VALID as FEE_GROUPS_3
from
FEE_GROUPS,
FEES
where
FEE_GROUPS.ID = #{id} and
FEES.ID_FEE_GROUP = FEE_GROUPS.ID
order by
FEE_GROUPS.VALID desc, FEE_GROUPS.NAME, FEES.VALID_FROM desc
</select>

</mapper>

--------------------------------------------------------------------------------
--------

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//ibatis.apache.org//DTD iBatis Mapper 3.0 //EN"
"http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd">
<mapper namespace="mapper.Fee">

<resultMap id="map" type="model.Fee">
<id property="id" column="FEES_1" />
<result property="idFeeGroup" column="FEES_2" />
<result property="priceSeller" column="FEES_3" />
<result property="priceCallCentrum" column="FEES_4" />
<result property="priceOperator" column="FEES_5" />
<result property="validFrom" column="FEES_6" />
<result property="validTo" column="FEES_7" />
<result property="maxOperatorMeeting" column="FEES_8" />
<association property="feeGroup" resultMap="mapper.FeeGroup.map" />
</resultMap>

</mapper> 

Original issue reported on code.google.com by [email protected] on 17 May 2010 at 1:32

  • Merged into: #509

Problem with mapping result when calling procedures and using inline params

There is a found problem with result mapping when calling procedure and
using inline params.

This mapping works fine:

<parameterMap type="LRU" id="map1">
    <parameter property="id" mode="IN" jdbcType="NUMERIC"
javaType="java.lang.Long"/>
    <parameter property="result" mode="OUT" jdbcType="CURSOR" 
resultMap="com.company.CarMapper.car"/>
</parameterMap>

<select id="selectCar1" statementType="CALLABLE" parameterMap="map1">
    { call PACK1.GET_CAR(?,?) }
</select>



This work too, but not return correct object!
Instead mapped object I get: oracle.jdbc.driver.OracleResultSetImpl
Do I something wrong or is it a bug?

<select id="selectCar2" statementType="CALLABLE">
    { call PACK1.GET_CAR(
        #{id, mode=IN, jdbcType=NUMERIC, javaType=java.lang.Long},
        #{result, mode=OUT,jdbcType=CURSOR, resultMap=com.company.CarMapper.car})
}
</select>


I use java iBatis 3.0.

Original issue reported on code.google.com by [email protected] on 2 Jun 2010 at 7:37

Wildcard Mapping

What version of the MyBatis are you using?
Mybatis 3.0.1 GA

Please describe the problem.  Unit tests are best!
May I use wildcard mapping in mybatis?such as "org/example/mapper/*.xml" go
instead of "org/example/mapper/PersonMapper.xml"

What is the expected output? What do you see instead?


Please provide any additional information below.


Original issue reported on code.google.com by [email protected] on 4 Jun 2010 at 1:41

  • Merged into: #365

Batch inserts for multiple tables

ibatis version: 2.3.4.726

By default for batch inserts ibatis caches the prepared statements in list and 
always re-uses the last statement for table inserts.  This model works for 
batch inserts for a single table.  However, we have a requirement where we need 
to do batch inserts into several tables in a single transaction.  Since ibatis 
is designed for batch inserts to a single table, using multi table insert gives 
us pathetic performance, as ibatis creates a new PreparedStatement for every 
query (engaging database cursor as well).
I looked at the source code and modified SqlExecutor==>addBatch() and 
executeBatch() method.  This method uses a Map instead of a list.  
Corresponding changes are done to populate the map and retrieve from map.  
Following is the code.

    private Map<String,PreparedStatement> statementMap = new HashMap<String,PreparedStatement>();

    public void addBatch(StatementScope statementScope, Connection conn, String sql, Object[] parameters) throws SQLException {
      PreparedStatement ps = null;
      //if (currentSql != null && currentSql.equals(sql)) {
      if (currentSql != null && statementMap.containsKey(currentSql)) {
        //int last = statementList.size() - 1;
        ps = (PreparedStatement) statementMap.get(currentSql);
      } else {
        ps = prepareStatement(statementScope.getSession(), conn, sql);
        setStatementTimeout(statementScope.getStatement(), ps);
        currentSql = sql;
        statementList.add(ps);
        statementMap.put(currentSql,ps);
        batchResultList.add(new BatchResult(statementScope.getStatement().getId(), sql));
      }
      statementScope.getParameterMap().setParameters(statementScope, ps, parameters);
      ps.addBatch();
      size++;
    }

    public int executeBatch() throws SQLException {
      int totalRowCount = 0;
      Collection<PreparedStatement> psColl = statementMap.values();
      //for (int i = 0, n = statementList.size(); i < n; i++) {
      Iterator<PreparedStatement> it = psColl.iterator();
      //for (int i = 0, n = psColl.size(); i < n; i++) {
      while(it.hasNext()){
        //PreparedStatement ps = (PreparedStatement) statementList.get(i);
       PreparedStatement ps = it.next();
        int[] rowCounts = ps.executeBatch();
        for (int j = 0; j < rowCounts.length; j++) {
          if (rowCounts[j] == Statement.SUCCESS_NO_INFO) {
            // do nothing
          } else if (rowCounts[j] == Statement.EXECUTE_FAILED) {
            throw new SQLException("The batched statement at index " + j + " failed to execute.");
          } else {
            totalRowCount += rowCounts[j];
          }
        }
      }
      return totalRowCount;
    }


Que: After making these changes everything works for us and the performance is 
very good as it starts using cached PreparedStatements.  Does it look like a 
proper implementation?  Will it have any other impact that I may not have seen 
yet?

-- Nitin

Original issue reported on code.google.com by [email protected] on 15 Jun 2010 at 4:12

Support for vararg values

Reporter:    Jan Novotný

Mapper method with signature:

List<Product> getProductsById(int... id);

And corresponding statement:

<select id="getProductsById"
resultMap="cz.novoj.ibatis.ProductMapper.thinProduct">
        select product.*, productGroup.name as groupName,
productGroup.groupType
            from product
            inner join productGroup on idGroup = productGroup.id
        where product.id in
              <foreach collection="array" item="item" open="(" close=")"
separator=", ">
                  #{item}
              </foreach>
    </select>

Fails with exception:

Caused by: java.lang.ClassCastException: [I cannot be cast to
[Ljava.lang.Object;
at
org.apache.ibatis.builder.xml.dynamic.ExpressionEvaluator.evaluateIterable(Expre
ssionEvaluator.java:29)
at
org.apache.ibatis.builder.xml.dynamic.ForEachSqlNode.apply(ForEachSqlNode.java:3
5)
at
org.apache.ibatis.builder.xml.dynamic.MixedSqlNode.apply(MixedSqlNode.java:14)
at
org.apache.ibatis.builder.xml.dynamic.DynamicSqlSource.getBoundSql(DynamicSqlSou
rce.java:22)
at
org.apache.ibatis.mapping.MappedStatement.getBoundSql(MappedStatement.java:198)
at
org.apache.ibatis.executor.BaseExecutor.createCacheKey(BaseExecutor.java:114)
at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:83)
at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:68)
at
org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSessio
n.java:59)

This is because int[] cannot be casted to Object[] directly.

See:

http://stackoverflow.com/questions/1115230/casting-object-array-to-integer-array
-error

Original issue reported on code.google.com by [email protected] on 17 May 2010 at 1:36

  • Merged into: #209

include mappers.xml in Configuration.xml

Reporter:    carlou

 now:
<configuration>
     <mappers>
         <mapper ..../>
     </mappers>
</configuration>

hope:
<configuration>
     <include href="com/mappers.xml"/>
     <include href="com/mappers1.xml"/>
     <include href="com/mappers2.xml"/>
</configuration>

mappers.xml mappers1.xml ...:
<mappers>
     <mapper .../>
     .....
</mappers>
 Description    
   now: <configuration>      <mappers>          <mapper ..../>     
</mappers> </configuration> hope: <configuration>      <include
href="com/mappers.xml"/>      <include href="com/mappers1.xml"/>     
<include href="com/mappers2.xml"/> </configuration> mappers.xml
mappers1.xml ...: <mappers>      <mapper .../>      ..... </mappers>
    Show »

Original issue reported on code.google.com by [email protected] on 17 May 2010 at 1:27

Patch to allow use of templates for 'migration new'

What version of the MyBatis are you using?
3.0.0.201, moving to 3.0.0.243


Please describe the problem.  Unit tests are best!
We thought it would be nice to provide the ability to create a default template 
that the 'migrate new' command could consume.  In our case, we have SQL that 
needs to be in all scripts.  If this SQL was included in a default template, we 
wouldn't have to enter it in manually for every script we create.  I would 
think this would be useful for the rest of the community as well.

Basically, you would create a $MIGRATIONS_HOME location, and include a 
migrations.properties file in that location.  This properties file will include 
the default location for the new_command template.  This patch will use that 
configured template.  If the configuration is not there, the default template 
used will be the myBatis packaged template.  I also have included support to 
use a --template= argument for flexibility (This overrides the $MIGRATIONS_HOME 
configuration).

What is the expected output? What do you see instead?
All new scripts created with migrate new will be created with a configured 
template by default.

Please provide any additional information below.
I have made code changes, with unit tests, and example configuration to support 
this feature request.
All modified, new, and configuration files are attached to this request, along 
with a patch/diff file (myBatisMigrationNewCommandPatch.tar.gz)

Thanks,
Mike Taylor
Senior Software Engineer
Citrix Online


Original issue reported on code.google.com by [email protected] on 10 Jun 2010 at 1:51

Attachments:

AutoGeneratedKey support for Oracle

Reporter:    Milos Zikic

It seams that iBatis doesn't make the prepared statement correctly for
Oracle so the autogenerated key functionality doesn't work and you get the
exception:

Caused by: java.sql.SQLException: Unsupported feature
at
oracle.jdbc.driver.OracleReturnResultSet.findColumn(OracleReturnResultSet.java:1
844)
at oracle.jdbc.driver.OracleResultSet.getInt(OracleResultSet.java:388)
at
org.apache.ibatis.type.IntegerTypeHandler.getNullableResult(IntegerTypeHandler.j
ava:17)
at org.apache.ibatis.type.BaseTypeHandler.getResult(BaseTypeHandler.java:24)
at
org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator.processAfter(Jdbc3KeyGenerat
or.java:38)

This is just a hint:

In order for Oracle to return generated key the array of ids needs to be
passed on in the Prepared Statement. Something like this

PreparedStatement pstmt =
  con.prepareStatement("INSERT INTO test (description) " +
                        "VALUES (:description)",
                             new String[] { "id"}); 

Original issue reported on code.google.com by [email protected] on 17 May 2010 at 1:40

Can I use ibatis in C in future?

Can I use ibatis in C in future?

I used ibatis one year ago, no I must develop in c.
I have to work with sqlite3 in c, so I wander if I can use ibatis for database 
operations?

Is possible to use mybatis.c in future?

Thanks a log.

Original issue reported on code.google.com by [email protected] on 10 Jun 2010 at 5:19

How to use transaction in ibatis3?

What version of the MyBatis are you using?
ibatis3.0.1

I used in this way, but it seems no transaction(SAMPLE 1):

SqlSessionFactoryBean sqlSessionFactory = ...
SqlSession session = null;
try {
   session = sqlSessionFactory.getObject().openSession();
   ... ...
   session.commit();
}
catch(Exception e)
{
   if(session != null) session.rollback();
}
finally
{
   if(session != null) session.close();
}


--------------------------
then I change to(SAMPLE 2):
SqlSessionFactoryBean sqlSessionFactory = ...
SqlSession session = null;
try {
   session = sqlSessionFactory.getObject().openSession();
   session.getConnection().setAutoCommit(false);
   ... ...
   session.getConnection().commit();
}
catch(Exception e)
{
   if(session != null) session.getConnection().rollback();
}
finally
{
   if(session != null) session.close();
}

It works fine. why does (SAMPLE 1) no effect?

Original issue reported on code.google.com by [email protected] on 13 Jun 2010 at 8:53

Allow the results annotation to specify an existing result map id

Reporter:    Paul Trepagnier

Instead of requiring a user of the @SelectProvider or @Select annotation to
create an annotation base result mapping, allow the user to specify an
existing result map instead. I propose adding a property to @Results that
is an existing result map id. This allows effective combination of dynamic
sql generation with an existing result map.

Original issue reported on code.google.com by [email protected] on 17 May 2010 at 1:40

  • Merged into: #1

Immutable POJO fails to load when lazyLoading is enabled

Reporter:    Jan Novotný

Immutable POJO fails to load when lazyLoading is enabled with exception:

Caused by: java.lang.IllegalArgumentException: Superclass has no null
constructors but no arguments were given
at net.sf.cglib.proxy.Enhancer.emitConstructors(Enhancer.java:721)
at net.sf.cglib.proxy.Enhancer.generateClass(Enhancer.java:499)
at
net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.jav
a:25)
at
net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)
at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:285)
at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:663)
at
org.apache.ibatis.executor.loader.ResultObjectProxy$EnhancedResultObjectProxyImp
l.createProxy(ResultObjectProxy.java:34)
at
org.apache.ibatis.executor.loader.ResultObjectProxy.createProxy(ResultObjectProx
y.java:17)
at
org.apache.ibatis.executor.resultset.FastResultSetHandler.createResultObject(Fas
tResultSetHandler.java:270)
at
org.apache.ibatis.executor.resultset.FastResultSetHandler.getRowValue(FastResult
SetHandler.java:170)
at
org.apache.ibatis.executor.resultset.FastResultSetHandler.handleRowValues(FastRe
sultSetHandler.java:129)
at
org.apache.ibatis.executor.resultset.FastResultSetHandler.handleResultSet(FastRe
sultSetHandler.java:105)
at
org.apache.ibatis.executor.resultset.FastResultSetHandler.handleResultSets(FastR
esultSetHandler.java:95)
at
org.apache.ibatis.executor.statement.PreparedStatementHandler.query(PreparedStat
ementHandler.java:40)
at
org.apache.ibatis.executor.statement.RoutingStatementHandler.query(RoutingStatem
entHandler.java:55)
at org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:41)
at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:90)
at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:68)
at
org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSessio
n.java:59)
... 36 more

I guess the source of the problem is usage of static method:

Enhancer.create(type, new EnhancedResultObjectProxyImpl(target, lazyLoader));

That doesn't allow to specify constructor arguments, thought iBatis know
them. This will effectively limit using immutable objects with iBatis as
lazy loading is set globally and is pretty often used.

Original issue reported on code.google.com by [email protected] on 17 May 2010 at 1:34

Schema Migrations - Statement commit not working as expected

What version of the MyBatis are you using?
3.0.1

Please describe the problem.  Unit tests are best!
Executed an entire script in one transaction, using the property:
auto_commit=false

Create a script with one or more correct statements, then deliberately have
an error in the migration script - this is to test if the whole script will
execute in a single transaction, for example:
--// Test
-- Migration SQL that makes the change goes here.
INSERT INTO "SEQUENCE" VALUES ('MY_SEQ', 100)
/
SELECT * FROM "SEQUENCEr"
/
--//@UNDO
-- SQL to undo the change goes here.
DELETE FROM "SEQUENCE" WHERE SEQ_NAME = 'MY_SEQ'
/

What is the expected output? What do you see instead?
Expected: The INSERT would not be committed
Actual: The INSERT is committed i.e it ran in it's own transaction

Please provide any additional information below.
I have mentioned the above issue on the mailing list and Clinton Begin has
confirmed it to be a bug, with the resolution most probably being: 
Line 205 in ScriptRunner should not be a connection.commit()

Clinton also mentioned that additional testing is required before the fix
can be committed.



Original issue reported on code.google.com by [email protected] on 28 May 2010 at 7:52

NullPointerException in ReuseExecutor.hasStatementFor()

Hi--

I have found that it is possible to encounter an exception in
ReuseExecutor.hasStatementFor() under certain conditions. I can do some
further recon to figure out exactly what conditions are necessary to get
the exception if that would be helpful, but what I know at the moment :

1) I do some work (in my case it's an INSERT) and then commit()
2) I happen to be using "autocommit" currently, not sure if that is a factor

The first time (or it may be the second time) my app does a commit() for a
given SQL statement, it encounters the exception. Then for all subsequent
executions there is no problem.

I've done a bit of debugging (just haven't had much time today yet) and
found that the error occurs here, which is at line 68 of ReuseExecutor in
the mybatis RC sources:

return statementMap.keySet().contains(sql) &&
!statementMap.get(sql).getConnection().isClosed();

When my exception occurs, keySet().contains(sql) returns true but
statementMap.get(sql).getConnection() returns null (possibly discarded by
the underlying Statement after the first commit?), thus you get a NPE when
isClosed() gets called. It seems to me that the code should maybe just
check for a null here. It's more than possible that I am doing something
wrong/unrecommended on my side (I'm in "hack" mode currently) but since it
is possible to get this problem then it seems it would be nice to make a
null-check part of the above test, or throw a descriptive exception message
if this particular situation arises.

I think just the following would do it:

return statementMap.keySet().contains(sql) &&
statementMap.get(sql).getConnection() != null &&
!statementMap.get(sql).getConnection().isClosed();

Again, I'm not saying I'm not doing something stupid which makes the NPE
possible in the first place; I probably am.  :)

Thanks
nate

Original issue reported on code.google.com by [email protected] on 2 Jun 2010 at 3:33

@SelectKey annotation

When trying @Insert annotation I found out, that there is no mean how to
specify primary key conciliation. Something like @SelectKey would be
necessary but such annotation doesn't exist. This means, that for
annotation based approach the only way are autogenerated keys (usable only
in case of few database engines) and @Option annotation with keyProperty
attribute set.

Original issue reported on code.google.com by [email protected] on 17 May 2010 at 1:33

Allow XMLConfigBuilder to read more than one config file.

Reporter:    Martin Ellis

Originally reported here:
http://www.mail-archive.com/[email protected]/msg14963.html

The iBATIS configuration file allows a number of different
environments (including database names and credentials) to be
specified. These are identified by environment name. The
configuration file is parsed by the XMLConfigBuilder class.

The XMLConfigBuilder constructor (the class that parses the config
file) creates a new Configuration instance per XMLConfigBuilder
instance, and it's only possible to specify a single Reader for a
given XMLConfigBuilder.

It'd be good to be able to separate out environment specific config
data from other ibatis config.

This means that it's not possible to keep the type aliases in an XML file
in a library, and the environments in a separate XML file in applications
using that library, and have the two combined at runtime.

Original issue reported on code.google.com by [email protected] on 17 May 2010 at 1:41

Generated keys with batch executor

Hello!

MyBatis version in use is 3.0.1.

Generated keys in <insert>s (both defined by @useGeneratedKeys and
<selectKey>) apparently do not work with BATCH executor: the setter for
@keyProperty is not invoked.

As far as I understand MyBatis code, in both cases the batch executor is
not flushed (contrary to regular <select>s):
 * SelectKeyGenerator uses separate executor for its <selectKey> query,
leaving batch executor's queue unaffected;
 * Jdbc3KeyGenerator invokes Statement.getGeneratedKeys() prior to the
statement's actual execution, since the statement is still in the batch
executor's queue.

Changing the executor type to SIMPLE or REUSE immediately makes the
generates keys work fine. If required, I will try to prepare a simple
project illustrating the issue.

Thanks!

Original issue reported on code.google.com by s.volchkov on 7 Jun 2010 at 6:14

Add 'void select(String statement, ResultHandler handler)' to org.apache.ibatis.session

Reporter:    François Schiettecatte

There are only two select() methods in org.apache.ibatis.session:

 void select(String statement, Object parameter, ResultHandler handler);

 void select(String statement, Object parameter, RowBounds rowBounds,
ResultHandler handler);

Would be nice to add this one for symmetry:

 void select(String statement, ResultHandler handler); 

Original issue reported on code.google.com by [email protected] on 17 May 2010 at 1:32

how intergrate mybastis3.0 and spring 3?

What version of the MyBatis are you using?
3.0.1

Please describe the problem.  Unit tests are best!
how to config the mybatis in app-context.xml(spring conf file)

What is the expected output? What do you see instead?
2 framework can work together well.  or with other ioc framework(e.g. guice)

Please provide any additional information below.


Original issue reported on code.google.com by [email protected] on 18 Jun 2010 at 1:58

Support iterator as result object

Currently using myIbatis 3.0.1

A great feature for Ibatis would be to support Iterators as result objects for 
mappers, in addition to lists, to make it possible to avoid loading the full 
result set in memory before processing. This is especially useful in cases 
where the result set is huge.

The ideal signature would be something of the kind

Iterator<BEAN> selectAll();

This would be extremely useful in situations where only one property of a bean 
is used: the preperty could be extracted of each bean, and added in a list. 
That way, much less memory could be used. I know that I could write a different 
query to handle this situation, but writing less SQL makes me happy :)

Original issue reported on code.google.com by [email protected] on 14 Jun 2010 at 2:03

result rows are dropped because cacheKey ignores nested properties in ResultMap

Reporter:    Marc-Olivier Fleury
Affects Version/s:       3.0 GA Candidate 

NestedResultSetHandler does not take nested result map into account when
creating cache keys. As a result, if the only columns that differ apply to
nested properties, rows are dropped.

NestedResultSetHandler.java:213
 private void createRowKeyForMappedProperties(ResultSet rs, CacheKey
cacheKey, List<ResultMapping> resultMappings) {
    for (ResultMapping resultMapping : resultMappings) {
      if (resultMapping.getNestedQueryId() == null &&
resultMapping.getNestedResultMapId() == null) {
        final String column = resultMapping.getColumn();
        final TypeHandler th = resultMapping.getTypeHandler();
        if (column != null) {
          try {
            final Object value = th.getResult(rs, column);
            if (value != null) {
              cacheKey.update(column);
              cacheKey.update(value);
            }
          } catch (Exception e) {
            //ignore
          }
        }
      } /* ELSE PART MISSING*/
    }
  }

This causes rows to be dropped.

NestedResultSetHandler.java:59
protected void handleRowValues(ResultSet rs, ResultMap resultMap,
ResultHandler resultHandler, RowBounds rowBounds) throws SQLException {
    final DefaultResultContext resultContext = new DefaultResultContext();
    skipRows(rs, rowBounds);
    while (shouldProcessMoreRows(rs, resultContext, rowBounds)) {
      final ResultMap discriminatedResultMap =
resolveDiscriminatedResultMap(rs, resultMap);
      final CacheKey rowKey = createRowKey(discriminatedResultMap, rs);
      final boolean knownValue = globalRowValueCache.containsKey(rowKey);
      Object rowValue = getRowValue(rs, discriminatedResultMap, rowKey);
      if (!knownValue) { /*THIS CHECK CAUSES THE ROW TO BE DROPPED IF ONLY
NESTED COLUMNS ARE DIFFERENT*/
        resultContext.nextResultObject(rowValue);
        resultHandler.handleResult(resultContext);
      }
    }
  }

Original issue reported on code.google.com by [email protected] on 23 May 2010 at 1:38

suggest ibatis can support *.xml mappers xml file

In mybatis ,in order to load mapper xml files ,we have to write all the xml 
file names . like this :
<mappers>
<mapper resource="com/mytest/sqlmap-a.xml"/>
<mapper resource="com/mytest/sqlmap-b.xml"/>
</mappers>


instead of this,I hope I can write like this:
<mappers>
<mapper resource="com/mytest/sqlmap-*.xml"/>
</mappers>

and mybatis can auto load all the files in "com/mytest/" which name start 
"sqlmap".

That's useful..Isn't right? what do you think ?


Original issue reported on code.google.com by [email protected] on 11 Jun 2010 at 8:33

  • Merged into: #32

When building SqlSessionFactory without XML, it should be possible to add xml mapper file

Reporter:    Igor Milina

Currently, when building SqlSessionFactory without XML it is only possible
to add mapper classes like this:

configuration.addMapper(BlogMapper.class);

I understand that iBATIS will automatically look for and load a peer XML
file if it exists (in this case, BlogMapper.xml would be loaded based on
the classpath and name of BlogMapper.class).

But this approach requires that BlogMapper class exists.
It should be possible to add BlogMapper.xml directly for users that wish to
use just .xml mappings without java interface.

Original issue reported on code.google.com by [email protected] on 17 May 2010 at 1:43

Support multiple character sets (parse XML from InputStream vs. Reader)

Reporter:    Henrik Kaipe

iBATIS-3 currently parses XML from Reader instances. When Reader instances
are created by the class Resources, then premature assumptions are made
about their charsets. - Charset is assumed to be the platform's default
charset or whatever is the current value of the field Resources.charset -
but the charset defined in the xml header is ignored!!

It would be better to parse the XML from InputStream, so that the
XML-framework will get the chance to determine charset on its own from the
XML-header or - in case the header does not specify charset - rely on the
XML-framework's ability to make charset assumptions, instead of having
iBATIS interfere.

This is probably not much of an issue in the English-speaking part of the
world but where I live it is not uncommon to encounter a project with
XML-files that have different charsets.

Older versions of iBATIS have relied on parsing XML from Reader, which
could be justified by the quality of the XML-frameworks of the old days,
but today it is no longer justified. - The introduction of iBATIS-3
provides a convenient opportunity to fully abandon the Reader usage and
start to parse XML from InputStream exclusively.

Original issue reported on code.google.com by [email protected] on 17 May 2010 at 1:37

add resultMap attribute to constructor/arg element

Reporter:    Ostap Bender

Hi All,

I guess this is a corner case but it is pretty important one for projects
with legacy data models.
Let say there is a table in DB that contains:

Column Type
id int
s1 string
s2 string
s3 string


Also let say it is modeled (historically) by two immutable objects:

public class ObjX
{
private final int id;
private final String s1;
private final ObjY objY;

public ObjX( int id, String s1, ObjY objY )
{
...
}
}

public class ObjY
{
private final String s2;
private final String s3;

public ObjY( String s2, String s3 )
{
...
}
}

In this case there seems to be no way to build a result map for ObjX in
iBatis without changing ObjX code but what if we cannot change it? And the
requirement is to create objects via constructors only.

It would be nice if we could use resultMap in <constructor>/<arg> element.
This way one could write something like:

<resultMap type="ObjX" id="ObjXResult">
        <constructor>
            <idArg column="id" javaType="_int" />
            <arg column="s1" javaType="String" />
            <arg javaType="ObjY" resultMap="ObjYResult"/>
        </constructor>
</resultMap>

<resultMap type="ObjY" id="ObjYResult">
        <constructor>
            <arg column="s2" javaType="String" />
            <arg column="s3" javaType="String" />
        </constructor>
</resultMap>

Comparable result could be achieved with TypeHandler but it will require
column names to be hard-coded in the TypeHandler implementation also will
require adding one TypeHandler per each such a case.

Original issue reported on code.google.com by [email protected] on 17 May 2010 at 1:38

Optimization of Executor.createCacheKey() method needed

Reporter:    Igor Milina

Method createCacheKey() in BaseExecutor class needs performance
optimization. If cache is used, this method is called several times during
one database select operation. During execution, method is recreating
complete mapped sql node, which is very intensive operation.

The performance of this method is making cache operations performs slow.
This is even more observable if mapped statement (that is being cached) is
complex. 

Original issue reported on code.google.com by [email protected] on 17 May 2010 at 1:42

Oracle refcursor in output variable: nested mapper not recognized as being nested

What version of the MyBatis are you using?
MyBatis v3.0

There is a bug when referring to a nested map definition in an
output variable.  For example, given the following select to call an
Oracle stored procedure:

        <select statementType="CALLABLE" id="getUserByAlias"
                parameterType="MyBatisBean" resultType="object">
                call PKG_USER_DATA_SERVICE_MYBATIS.get_user_by_alias (
                #{alias}

,#{retvalUsers,mode=OUT,jdbcType=CURSOR,javaType=java.sql.ResultSet,resultMap=De
tailedObjUserVo}
                )
        </select>

I have the following nested resultMap definition:

        <resultMap id="DetailedObjUserVo" type="ObjUserVo">
                <id property="userId" column="user_id" />
                <result property="firstName" column="first_name" />
                <result property="middleName" column="middle_name" />
                <result property="lastName" column="last_name" />
                <collection property="accounts" javaType="List"
                        ofType="ObjAccountVo">
                        <id property="accountId" column="account_id" />
                        <result property="alias" column=" alias" />
                </collection>
        </resultMap>

Unfortunately MyBatis doesn't seem to be recognizing the resultMap as
being nested.  For example, in a simple case I should be getting one
user with 2 accounts in the collection, but instead I am getting 2
users, each with zero accounts.  I've stepped through the code with the
debugger, and I confirm that in the following Configuration code the
mappedStatement.hasNestedResultMaps() method is returning false and
therefore I am *not* getting an instance of NestedResultSetHandler,
which then results in he creation of two users each with no accounts:

public ResultSetHandler newResultSetHandler(Executor executor,
MappedStatement mappedStatement, RowBounds rowBounds, ParameterHandler
parameterHandler, ResultHandler resultHandler, BoundSql boundSql) {
    ResultSetHandler resultSetHandler =
mappedStatement.hasNestedResultMaps() ?
        new NestedResultSetHandler(executor, mappedStatement,
parameterHandler, resultHandler, boundSql, rowBounds)
        : new FastResultSetHandler(executor, mappedStatement,
parameterHandler, resultHandler, boundSql, rowBounds);
    resultSetHandler = (ResultSetHandler)
interceptorChain.pluginAll(resultSetHandler);
    return resultSetHandler;
  }

I correctly get one user with 2 accounts when I use the debugger to
cause mappedStatement.hasNestedResultMaps() to return true.

Original issue reported on code.google.com by [email protected] on 2 Jun 2010 at 1:07

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.