私はDBからデータを抽出する必要があるいくつかのプロジェクトに取り組んでおり、Spring MVCを使用してデータを選択するためにDBからモデルを構築しています。
これが私の問題ですJSPページ:
<form action="result" method="get" >
<table>
<thead>
<tr>
<th>Date to select:</th>
<th>Name to select:</th>
<th>Type to select:</th>
</tr>
</thead>
<tbody>
<tr>
<td><form:select path="listOfDates">
<form:option value="NONE"> --SELECT--</form:option>
<form:options items="${listOfDates}"></form:options>
</form:select>
</td>
<td><form:select path="listOfInstitutionsNames">
<form:option value="NONE"> --SELECT--</form:option>
<form:options items="${listOfInstitutionsNames}"></form:options>
</form:select>
</td>
<td>
<form:select path="listOfInstitutionsTypes">
<form:option value="NONE"> --SELECT--</form:option>
<form:options items="${listOfInstitutionsTypes}"></form:options>
</form:select>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td><input type="submit" value="Извлечь"/></td>
</tr>
</tfoot>
</table>
</form>
ご覧のとおり、Spring
タグライブラリの<form:select>
を使用してみます。
質問:
しかし、これで私のモデルを準備しているときcontroller:
@Controller
public class HomeController{
@Autowired
private ControllerSupportClass controllerSupportClass;
@RequestMapping(value="/search", method=RequestMethod.GET)
public String search(Model model) {
List<Date> listOfDates = controllerSupportClass.findAllDatesForm();
List<String> listOfInstitutionsNames = controllerSupportClass.findAllInstitutionsForm();
List<String> listOfInstitutionsTypes = controllerSupportClass.findAllTypesForm();
model.addAttribute("listOfInstitutionsTypes", listOfInstitutionsTypes);
model.addAttribute("listOfInstitutionsNames", listOfInstitutionsNames);
model.addAttribute("listOfDates", listOfDates);
return "search";
}
@RequestMapping(value ="/result", method=RequestMethod.GET)
public String SecondActionPage(@RequestParam String particularDate,
@RequestParam String nameOfInstitution,
@RequestParam String typeName,
Model model) throws Exception {
if(particularDate !="" && nameOfInstitution.trim() !="" && typeName.trim()=="") {
controllerSupportClass.findWithDateAndName(nameOfInstitution, particularDate, model);
} else if(particularDate.trim() !="" && nameOfInstitution.trim() =="" && typeName.trim() !="") {
controllerSupportClass.findWithAddedDateAndType(typeName, particularDate, model);
} else if(particularDate.trim() !="" && nameOfInstitution.trim() =="" && typeName.trim() ==""){
controllerSupportClass.findWithAddedDate(particularDate, model);
} else if(particularDate.trim() !="" && nameOfInstitution.trim() !="" && typeName.trim() !="") {
throw new Exception("Search by choose all parameters is not exceptable");
} else {
throw new Exception("You didn't put any search parameters");
}
return "search";
}
}
次のようなエラーが表示されます:
WARN:org.springframework.web.servlet.PageNotFound-'appServlet'という名前のDispatcherServletにURI [/ controller /]のHTTPリクエストのマッピングが見つかりませんHibernate:個別のcreationda0_.DATE_IDをDATE1_0_、creationda0_.CHILD_ADMISSION_DATEをCHILD2_0_、creationda0_として選択します。 CHILD_GO_SCHOOL_DATE as CHILD3_0_、creationda0_.PARTICULAR_DATE as PARTICULAR4_0_、creationda0_.VERSION as VERSION0_ from CREATION_DATE creationda0_ WARN:org.hibernate.util.JDBCExceptionReporter-SQL Error:0、SQLState:S1009.DB.ERROR.org.ErrorException org.Error.org.Error.org.Error.org 00-00 'はJava.sqlとして表すことはできません。日付2013年6月19日3:26:53 PM org.Apache.catalina.core.StandardWrapperValve invoke SEVERE:Servlet.service()パス[/ controller]のコンテキストでサーブレット[appServlet]が例外をスローしました[リクエスト処理が失敗しました。ネストされた例外はorg.hibernate.exception.GenericJDBCException:クエリを実行できませんでした]根本原因Java.sql.SQLException:値 '0000-00 -00 'は表現できませんJava.sql.Dateとして
Entityクラスが必要な場合はここにありますJava.util
のDate
を使用していますが、@Temporal
アノテーションを使用して、SQLからユニットDate
に変換しています。理解する:
@Entity
@Table(name="CREATION_DATE")
public class CreationDate implements Serializable {
private int dateId;
@Id
@GeneratedValue(strategy=IDENTITY)
@Column(name="DATE_ID")
public int getDateId() {
return dateId;
}
public void setDateId(int dateId) {
this.dateId = dateId;
}
private int version;
@Version
@Column(name="VERSION")
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
private Date particularDate;
@Temporal(TemporalType.DATE)
@DateTimeFormat(pattern="yyyy-MM-dd")
@Column(name="PARTICULAR_DATE")
public Date getParticularDate() {
return particularDate;
}
public void setParticularDate(Date particularDate) {
this.particularDate = particularDate;
}
private Date childGoSchoolDate;
@Temporal(TemporalType.DATE)
@DateTimeFormat(pattern="yyyy-MM-dd")
@Column(name="CHILD_GO_SCHOOL_DATE")
public Date getChildGoSchoolDate() {
return childGoSchoolDate;
}
public void setChildGoSchoolDate(Date childGoSchoolDate) {
this.childGoSchoolDate = childGoSchoolDate;
}
private Date childAdmissionDate;
@Temporal(TemporalType.DATE)
@DateTimeFormat(pattern="yyyy-MM-dd")
@Column(name="CHILD_ADMISSION_DATE")
public Date getChildAdmissionDate() {
return childAdmissionDate;
}
public void setChildAdmissionDate(Date childAdmissionDate) {
this.childAdmissionDate = childAdmissionDate;
}
}
データ型変換の問題はMVCがString
を使用しているためであると想定していますが、実際の型はDate
です。
MySqlでは'0000-00-00'
は有効な日付と見なされますが、Java.sql.Dateとして表すことはできません。
日付が'0000-00-00'
の場合はNULLを返し、それ以外の場合は実際の値を返すクエリを使用できます。
SELECT
CASE WHEN `date`!='0000-00-00' THEN `date` END new_date
FROM
yourtable
または、これをデータソース接続文字列に追加できます。
zeroDateTimeBehavior=convertToNull
'0000-00-00'
としての日付は自動的にNULLに変換されます。
次のステートメントをJDBC-mysqlプロトコルに追加します。
"?zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=UTF-8&characterSetResults=UTF-8"
例えば:
jdbc:mysql://localhost/infra?zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=UTF-8&characterSetResults=UTF-8
追加 zeroDateTimeBehavior=convertToNull
をjdbc接続URLに変更します。
String jdbcUrl="jdbc:mysql://localhost:3306/master_schema?zeroDateTimeBehavior=convertToNull"
これは常にNULL
の問題ではありません。データセットには05/23/2005
の形式の日付が含まれている可能性があり、ローダーを実行すると、DATEタイプの列に0000-00-00
が挿入されます。無効なDATE
、DATETIME
、またはTIMESTAMP
の値は、適切なタイプ(「0000-00-00」または「0000-00-00」の「ゼロ」値に変換されます00:00:00 ')(MySQLマニュアルから)
MySQLはSELECT
を使用して取得するときに、YYYY-MM-DD'
から'1000-01-01'
の範囲で'9999-12-31'
形式の値を取得します。つまり、すべての0000-00-00
が台無しになり始めます。
したがって、NULLs
だけでなく、MySQLでサポートされていない日付形式にも注意してください。
RELAXEDモードがサポートされており、/
の05/23/2005
のように、任意の文字を区切り文字として使用できます。これも試してみてください。
MySQLを使用していると思いますが、日付列は必須ではないため、NULLを含めることができますが、MySQLは馬鹿げたことを行い、MySQLサーバーの設定を修正しない限り、NULLの代わりに0000-00-00を返します。
私にとっては、単に以下がうまくいきました。 @ Yogesh H Bhosaleと@ fthiellaのおかげで、この同じQ-Aスレッドで回答が得られ、ヒントを見つけて改善しました。
コードスニペット:
接続文字列:
private static String CONNECTION_STR = "jdbc:mysql://localhost:3306/water_billing?zeroDateTimeBehavior=convertToNull";
SQL-DB実装:
また、返されたデータセットからのデータ(日付フィールド)抽出時のNullポインター例外を防ぐために、次のコードをPrepared Statementに追加します。
Connection conn = DriverManager.getConnection(CONNECTION_STR,USERNAME,PASSWORD); // Get connection to the DB to execute the query. You will have to handle exceptions here too..
String SQL = "SELECT dateField FROM my_payments_tbl";
ResultSet rs = conn.createStatement().executeQuery(SQL);
LocalDate prvPaymentDate = null;
while (rs.next())
{
// Following is the next Important line.
prvPaymentDate = (rs.getDate(1) != null) ? rs.getDate(1).toLocalDate() : null; // Checks if it comes as a Null or a Real Java.sql.Date object.
// Depending on the value of the column in the current row, prvPaymentDate could be null.
// Specially as we instructed via the Connection String, 0000-00-00 00:00:00 will come now as SQL NULL objects.
// So we filter out them in the above line and assigns null, instead of LocalDate objects.
if (prvPaymentDate != null)
System.out.println("date "+prvPaymentDate.toString());
}
注:
よく理解するために、回答内のすべてのコメントを読んでください。