brunorozendo / log4jdbc-log4j2

Automatically exported from code.google.com/p/log4jdbc-log4j2
48 stars 39 forks source link

in log4jdbc-log4j2-jdbc3-1.16.jar,RdbmsSpecifics's formatParameterObject Date format may has bug #37

Closed belugaliu closed 5 years ago

belugaliu commented 6 years ago

i use the log4jdbc-log4j2-jdbc3-1.16.jar with hibernate-3.2.7.ga.jar and jtds-1.2.7.jar. i found if i use preparedStatement with hibernate like this:

 Object r = dzjzFoundationDao.getHibernateTemplate().execute(new HibernateCallback() {
            @Override
            public Object doInHibernate(Session session) throws HibernateException, SQLException {
                String hql = new String(
                    "SELECT new com.thunisoft.fy.dzjz.httpapi.prescanner.timer.bean.FeedbackInfoBean ( clfx.CBhDsf as cBhDsf, fd.NAjbs as nAjbs, " +
                            "fd.NJbfy as nJbfy, fd.NAjlb as nAjlb, jz.CMc as cAh, clfx.dtScanTimesstamp as dScanTimesstamp, clfx.CSerialNum as cSerialNum )" +
                                " FROM TYwgyDzjzPrescannerClfx clfx, TYwgyDzjzPrescannerInfoFeedback fd, TYwgyDzjzJz jz" +
                                    " WHERE fd.CBhClfx = clfx.CBh AND clfx.CBhAj = jz.CBhAj AND clfx.NState = 1 AND clfx.NJbfy = :JBFY"+
                                        " AND clfx.dtScanTimesstamp > (:start) AND clfx.dtScanTimesstamp < (:end)"
                        );
                Query q = session.createQuery(hql);
                try {
                    q.setParameter("JBFY", fyid);
                    q.setDate("start", beginDate);
                    q.setDate("end", endDate);
                } catch (ParseException e) {
                    throw new SQLException(String.format("%s or %s is not in a valid date format", begin, end), e);
                }
                return q.list();
            }
        });

ps: beginDate and endDate are java.util.Date class's instance. and them have time value(hh:mm:ss). when use hibernate Query.setDate, jtds will send date without time to DB server.


// jdtsPreparedStatement setParameter's code
if (x instanceof Date) {
    x = new DateTime((Date) x);
} else if (x instanceof Time) {
    x = new DateTime((Time) x);
} else if (x instanceof Timestamp) {
    x = new DateTime((Timestamp) x);
}

// net.sourceforge.jtds.jdbc.DateTime construtors's code
 DateTime(Date d) throws SQLException {
        dateValue = d;
        GregorianCalendar cal = new GregorianCalendar();
        cal.setTime(d);

        if (cal.get(Calendar.ERA) != GregorianCalendar.AD)
            throw new SQLException(Messages.get("error.datetime.range.era"), "22007");

        year   = (short)cal.get(Calendar.YEAR);
        month  = (short)(cal.get(Calendar.MONTH) + 1);
        day    = (short)cal.get(Calendar.DAY_OF_MONTH);
        // please notice next codes
        hour   = 0;
        minute = 0;
        second = 0;
        millis = 0;
        packDate();
        time = TIME_NOT_USED; 
        unpacked  = true;
    }

but log4jdbc.jar print sql with date and time,like this:

select tywgydzjzp0_.DT_SCANTIMESSTAMP,tywgydzjzp0_.C_BH_DSF as col_0_0_, tywgydzjzp1_.N_AJBS as col_1_0_, tywgydzjzp1_.N_JBFY as col_2_0_, tywgydzjzp1_.N_AJLB as col_3_0_, tywgydzjzj2_.C_MC 
as col_4_0_, tywgydzjzp0_.DT_SCANTIMESSTAMP as col_5_0_, tywgydzjzp0_.C_SERIALNUM as col_6_0_ from YWST.dbo.T_YWGY_DZJZ_PRESCANNER_CLFX tywgydzjzp0_, YWST.dbo.T_YWGY_DZJZ_PRESCANNER_FEEDBCK 
tywgydzjzp1_, YWST.dbo.T_YWGY_DZJZ_JZ tywgydzjzj2_ where tywgydzjzp1_.C_BH_CLFX=tywgydzjzp0_.C_BH and tywgydzjzp0_.C_BH_AJ=tywgydzjzj2_.C_BH_AJ and tywgydzjzp0_.N_STATE=1 
and tywgydzjzp0_.N_JBFY=2400 and tywgydzjzp0_.DT_SCANTIMESSTAMP>'12/06/2017 00:00:00.000' and tywgydzjzp0_.DT_SCANTIMESSTAMP<'12/06/2017 23:59:59.000'

and i found log4jdbc use pattern "MM/dd/yyyy HH:mm:ss.SSS" format date object in RdbmsSpecifics class.

  //RdbmsSpecifics
  protected static final String dateFormat = "MM/dd/yyyy HH:mm:ss.SSS";
    public String formatParameterObject(Object object)
    {
        if (object == null)
        {
            return "NULL";
        }

        if (object instanceof String)
        {
            return "'" + escapeString((String)object) + "'";
        }
        else if (object instanceof Date)
        {

            return "'" + new SimpleDateFormat(dateFormat).format(object) + "'";
        }
        else if (object instanceof Boolean)
        {
            return Properties.isDumpBooleanAsTrueFalse()?
                    ((Boolean)object).booleanValue()?"true":"false"
                        :((Boolean)object).booleanValue()?"1":"0";
        }
        else
        {
            return object.toString();
        }
    }

so, i think if Object is instance of Timestamp , use pattern "MM/dd/yyyy HH:mm:ss.SSS" format date object.
and if Object is instance of Date, use pattern "MM/dd/yyyy" format date object.

do you aceept what i want say?

brunorozendo commented 6 years ago

update jtds-1.2.7.jar to jtds-1.3.1.jar