импорт из файла CSV в SQLite

у меня есть 3 класса с таблицами баз данных и в каждый надо добавить некоторые столбцы из таблицы файла csv, есть у кого нибудь пример как происходит импорт данных из таблицы с расширением csv? или методичка? я искала, но не нашла. Помогите пожаалуйста

public class DBObjectType extends SQLiteOpenHelper {
public static final int DATABASE_VERSION=1;
public static final String DATABASE_NAME= "Inventory_Tracking";
public static final String TABLE_CONSTACTS= "constacts";
public static final String KEY_ID="id";
public static final String NAME="name";
public DBObjectType(@Nullable Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db)
{
db.execSQL("create table " + TABLE_CONSTACTS + "(" + KEY_ID
+ " integer primary key, " + NAME
+ " text " + ")");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("drop table if exists " + TABLE_CONSTACTS) ;
onCreate(db);
}
}

https://yadi.sk/d/BoFbuhyeIryP5Q (ссылка на файл csv)


Ответы (1 шт):

Автор решения: Дмитрий

Ситуация такова... Я написал вам пример парсера, модели и сервиса для сохранения в бд. Парсер работает, а сервис надо будет доделывать. поскольку настройки БД у каждого свои, мало того, БД у всех разная. нужен драйвер в зависимостях плюс урл, имя пользователя, пароль для доступа. У меня нет геттеров, сеттеров и прочего шаблонного кода, это генерирует зависимомть, именуемая ломбок (но вы можете изменить это). Плюс орм лайт на вашей совести, я использую ее здесь.

Итак, это мои зависимости :

compile group: 'org.projectlombok', name: 'lombok', version: '1.18.10'
annotationProcessor 'org.projectlombok:lombok:1.18.10'   
compile group: 'au.com.bytecode', name: 'opencsv', version: '2.4'
compile group: 'com.j256.ormlite', name: 'ormlite-core', version: '5.1'
compile group: 'com.j256.ormlite', name: 'ormlite-jdbc', version: '5.1'
compile group: 'javax.persistence', name: 'persistence-api', version: '1.0.2'
compile group: 'org.reflections', name: 'reflections', version: '0.9.10'
compile group: 'log4j', name: 'log4j', version: '1.2.17'

Теперь пишем класс - модель (вы создаете для моделей отдельный пакет, имя которого нужно будет указать в сервисе для ОРМ). Экземпляры этого класса получатся в результате распарсивания и их же мы используем для записи в БД с помощью нашей ОРМ.

import java.util.Map;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;

@lombok.Data
@lombok.NoArgsConstructor
@lombok.EqualsAndHashCode(callSuper = false)
@lombok.experimental.FieldDefaults(level = lombok.AccessLevel.PRIVATE)
@Entity(name = "book")
public class Book extends GeneratedObject {

    private static final long serialVersionUID = -1250491311329285427L;

    @Id
    //@GeneratedValue(strategy = GenerationType.IDENTITY)
    Long id;

    @Column(name = "inv_number")
    Long invNumber;

    @Column(name = "name")
    String name;

    @Column(name = "commissioning_date")
    String commissioningDate;

    @Column(name = "act_namber")
    String actNumber;

    @Column(name = "write_off_date")
    String writeOffDate;

    @Column(name = "write_off_act_number")
    String writeOffActNumber;

    @Column(name = "initial_cost")
    String initialCost;

    @Column(name = "object_placement")
    String objectPlacement;

    @Column(name = "responsible_name")
    String responsibleName;

    @Column(name = "responsible_phone")
    String responsiblePhone;

    @Column(name = "responsible_position")
    String responsiblePosition;

    @Column(name = "korpus_number")
    Integer korpusNumber;

    @Column(name = "audience_number")
    String audienceNumber;

    public Book(Map<String, String> values) {
        super(values);
        initFromCSV();
    }

    private void initFromCSV() {
        this.id = super.readLong("id");
        this.invNumber = super.readLong("Инвент.Номер");
        this.name = super.readString("Наименование объекта");  
        this.commissioningDate = super.readString("Дата ввода в эксплуатацию");
        this.actNumber = super.readString("№ акта ввода");        
        this.writeOffDate = super.readString("Дата списания");
        this.writeOffActNumber = super.readString("№ акта списания");
        this.initialCost = super.readString("Начальная стоимость");
        this.objectPlacement = super.readString("Уточнение размещения объекта учета");
        this.responsibleName = super.readString("ФИО ответственного");
        this.responsiblePhone = super.readString("Номер телефона ответственного");
        this.responsiblePosition = super.readString("Должность отвественного");
        this.korpusNumber = super.readInteger("№ копруса");
        this.audienceNumber = super.readString("№ аудитории");
    }

}

Супер класс для этой модели выглядит так(как и для всех ваших моделей)

import java.io.Serializable;
import java.util.Map;

@lombok.NoArgsConstructor
@lombok.EqualsAndHashCode
@lombok.ToString
public abstract class GeneratedObject implements Serializable {

    private static final long serialVersionUID = -5974468198694897022L;

    @javax.persistence.Transient
    private Map<String, String> values;

    public GeneratedObject(final Map<String, String> values) {
        this.values = values;
    }

    protected Integer readInteger(final String valueName) {
        try {
            return Integer.valueOf(this.values.get(valueName));
        } catch (NullPointerException e) {
            return null;
        }
    }

    protected Long readLong(final String valueName) {
        try {
            return Long.valueOf(this.values.get(valueName));
        } catch (NullPointerException e) {
            return null;
        }
    }

    protected Double readDouble(final String valueName) {
        try {
            return Double.valueOf(this.values.get(valueName).replace(",", ".").trim());
        } catch (NullPointerException e) {
            return null;
        }
    }

    protected String readString(final String valueName) {
        return valueName == null ? null : this.values.get(valueName.trim());
    }

}

Когда есть модель, напишем наш парсер. Я хочу, чтобы он был универсальным и мы переиспользовали его для остальных моделей.

import au.com.bytecode.opencsv.CSVReader;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class CsvParser {

    private final static Class[] CONSTRUCTORS_ARGS = {Map.class};

    public <T> List<T> loadCSV(final String csvPath, final Class<T> clazz) throws Exception {
        //read from resoursec folder
//        try (final InputStreamReader inputStreamReader = new InputStreamReader
//                (new BufferedInputStream(CsvParser.class.getClassLoader()
//                        .getResourceAsStream(csvPath)), Charset.defaultCharset())) {
        try (final InputStreamReader inputStreamReader = new InputStreamReader
                (new BufferedInputStream(new FileInputStream(csvPath)), Charset.defaultCharset())) {

            final List<String[]> rows = new CSVReader(inputStreamReader, ';').readAll();

            final String[] columnsNames = ((String[]) rows.remove(0));

            final List<T> valuesList = new ArrayList<>(rows.size());

            for (final String[] value : rows) {
                final Map<String, String> values = new LinkedHashMap(value.length);
                for (int i = 0; i < value.length; i++) values.put(columnsNames[i], value[i]);
                T t = clazz.getDeclaredConstructor(CONSTRUCTORS_ARGS).newInstance(values);
                valuesList.add(t);
            }            
            return valuesList;            
        }

    }

}

Вызов будет выглядеть так

List<Book> loadCSV = new CsvParser().loadCSV("invent.book.csv", Book.class);

Результат выполнения - коллекция объектов Book. Осталось записать в БД. Для эттого сделаем сервис леер. Чтобы не булировать код, создадим интерфейс и абстрактный класс с универсальной (основаной на дженериках) реализацией для стандартных методов работы с бд. Выглядит это так.

import java.util.List;

public interface BaseService <T extends GeneratedObject, ID> {
    T save(final T t);
    T findById(final ID id);    
    List<T> findAll();
    void delete(T t);
    void saveAll(List<T> ts);
}



import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.dao.DaoManager;
import com.j256.ormlite.jdbc.JdbcConnectionSource;
import com.j256.ormlite.support.ConnectionSource;
import com.j256.ormlite.table.TableUtils;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import javax.persistence.Entity;
import org.reflections.Reflections;

@lombok.extern.log4j.Log4j
public abstract class BaseServiceImpl <T extends GeneratedObject, ID> implements BaseService <T,ID>{

    private static final String ENTITY_PACKAGE_NAME = "PATH_TO_PACKAGE_WITH_ENTITY";

    private final static String DB_URL = "YOUR_DB_URL";    
    private final static String DB_USERNAME = "YOUR_DB_USERNAME"; 
    private final static String DB_PASSWORD = "YOUR_DB_PASSWORD"; 

    private static final ConnectionSource CONNECTION;    
    static {CONNECTION = createConnectionSource(DB_URL, ENTITY_PACKAGE_NAME, DB_USERNAME, DB_PASSWORD);}

    protected Dao<T, ID> dao;

    public BaseServiceImpl(final Class <T>clazz) {
        try {
            this.dao = DaoManager.createDao(CONNECTION, clazz);
        } catch (SQLException ex) {
            log.error(BaseServiceImpl.class.getName(), ex);
        }
    }

    @Override
    public T findById (final ID id) {
        try {
            return dao.queryForId(id);
        } catch (SQLException ex) {
            log.error("FindByName(): " + ex.getMessage());
            return null;
        }
    }

    @Override
    public List<T> findAll() {
        try {
            return dao.queryForAll();
        } catch (SQLException ex) {
            log.error("FindAll(): " + ex.getMessage());
            return null;
        }     
    }

    @Override
    public void delete(T t) {
        try {
            dao.delete(t);
        } catch (SQLException ex) {
            log.error("Delete(): " + ex.getMessage());
        }
    }

    @Override
    public T save(final T t) {
        try {
            final ID id = dao.extractId(t);
            if (id != null && dao.idExists(id)) dao.update(t);
            else dao.create(t);            
        } catch (SQLException ex) {
            log.error("Save(): " + ex.getMessage());
        }
        return t;
    }

    @Override
    public void saveAll(List<T> ts) {
        for (final T t : ts) save(t);
    }

    protected void dropAndStore(final Collection<T> t) throws SQLException {
        drop();
        create();
        if (t!=null) dao.create(t);
    }

    private void drop() throws SQLException {
        TableUtils.dropTable(dao, true);
    }

    private void create() throws SQLException {
        TableUtils.createTable(dao);
    }


    private static ConnectionSource createConnectionSource(final String dbUrl, final String packageName, String userName, String password) {
        if (userName==null || password==null) return createConnectionSource(dbUrl, packageName);
        try (final ConnectionSource connectionSource = new JdbcConnectionSource(dbUrl, userName, password)) {
            return createConnectionSource(connectionSource, packageName);
        } catch (SQLException | IOException e) {return null;}
    }

    private static ConnectionSource createConnectionSource(final String dbUrl, final String packageName) {
        try (final ConnectionSource connectionSource = new JdbcConnectionSource(dbUrl)) {
            return createConnectionSource(connectionSource, packageName);
        } catch (SQLException | IOException e) {
            return null;
        }
    }

    private static ConnectionSource createConnectionSource(final ConnectionSource connectionSource, final String packageName) {
        final Set<Class<?>> reflections = new Reflections(packageName).getTypesAnnotatedWith(Entity.class);
        for (final Class clazz : reflections) {
            log.info("Creating table '" + clazz.getName() + "'");
            try {
                TableUtils.createTableIfNotExists(connectionSource, clazz);
            } catch (SQLException e) {
                log.info("Table " + clazz.getName() + " already exist");
                //do nothing
            }
        }
        return connectionSource;
    }

}   

В классе BaseServiceImpl все статические методы отвечают за создание коннекта к бд и ее инициализацию. Это далеко не лучшая практика, поэтому вы можете изменить это. Важно получить объект ConnectionSource.

Теперь все просто. Поскольку все методы работы с бд реализованы на абстрактном уровне, наш сервис работы с бд для модели Book выглядит проще некуда (как и все остальные будущие сервисы), достаточно лишь унаследоваться от класса BaseServiceImpl.

public class BookService extends BaseServiceImpl{

public BookService() {
    super(Book.class);
}

}

Вот и все. В классе BaseServiceImpl вам нужно указать путь к пакету с классами-моделями, а также данные для подключения к бд.

Можете задавать вопросы)

→ Ссылка