Grails中如何将解析后的CSV数据保存至数据库?
Hey there! Looks like you've already nailed the CSV parsing part with Grails—nice work! Now let's get that parsed data mapped to your Data domain class and saved to the database. Here's a step-by-step breakdown of what you need to do:
First: Fix Up Your Domain Class
I noticed a couple of issues in your Data class definition: there's a duplicate data115 property and some unfinished underscores. Let's clean that up first to make sure it's valid:
class Data { String data1 Date data12 Date data13 Date data14 Date data15 String data16 String data17 String data18 String data19 String data110 String data111 String data112 String data113 String data114 String data115 String data116 String data117 String data118 String data119 String data120 static constraints = { // Add constraints as needed—for example, mark fields that can be null data1 nullable: true data12 nullable: true // Repeat for other fields based on your requirements } }
Second: Modify Your Parsing Code to Persist Data
Your existing code reads each line of the CSV, so we just need to map each element in the line array to the corresponding property in a Data instance, then save it. Important: Double-check that the index of each line element matches the correct property in your domain class (I've guessed based on your sample output, but adjust as needed):
def upload = { def f = request.getFile('filecsv') if (f.empty) { flash.message = 'file cannot be empty' render(view: 'uploadForm') return } else { def file = request.getFile('filecsv') // Use withReader to automatically close the stream and avoid resource leaks file.inputStream.withReader('UTF-8') { reader -> def csvReader = reader.toCsvReader(['separatorChar': '|']) csvReader.eachLine { line -> // Skip header row if your CSV has one (uncomment if needed) // if (line[0] == 'data1_header') return // Create a new Data instance and map CSV values to properties def dataInstance = new Data( data1: line[0], // Parse dates using the format from your CSV (yyyy-MM-dd in your sample) data12: line[1] ? Date.parse('yyyy-MM-dd', line[1]) : null, data13: line[2] ? Date.parse('yyyy-MM-dd', line[2]) : null, data14: line[4] ? Date.parse('yyyy-MM-dd', line[4]) : null, data15: line[14] ? Date.parse('yyyy-MM-dd', line[14]) : null, data16: line[5], data17: line[6], data18: line[8], data19: line[20], data110: line[21], data111: line[22], data112: line[23], data113: line[24], data114: line[25], data115: line[26], data116: line[27], data117: line[28], data118: line[29], data119: line[30], data120: line[31] // Add remaining properties by matching their CSV line index ) // Save the instance to the database if (dataInstance.save(flush: true, failOnError: true)) { println "Successfully saved record for: ${dataInstance.data1}" } else { // Print errors if save fails (great for debugging) println "Failed to save record: ${dataInstance.errors}" } } } // Let the user know the import worked flash.message = 'CSV data successfully imported!' redirect(action: 'uploadForm') } }
Key Things to Keep in Mind
- Date Format Matching: Make sure the format in
Date.parseexactly matches the date strings in your CSV. If you're unsure, useDate.parseOrDefaultor add a try-catch block to handle invalid dates. - Null Handling: CSV empty strings should be converted to
null(like in the date fields above) to avoid errors with non-string properties. - Batch Optimization: If you're importing a huge CSV, batch saves will boost performance—try flushing every 50-100 records or using a transaction for bulk operations.
- Validation: Use Grails domain constraints to enforce data rules (e.g., required fields, valid dates). The
failOnError: trueflag will throw an exception if validation fails, making debugging easier. - Resource Management: Using
withReaderensures the input stream gets closed properly, which prevents resource leaks.
Test It Out
Upload your CSV file after making these changes, then check your database (or use the Grails console) to confirm the records were saved. If you run into save errors, look at the console output for specific validation issues—adjust the property mapping or domain constraints as needed.
内容的提问来源于stack exchange,提问作者jenny sam

