Hibernate 多表映射(Mybatis,Springjdbc,Hibernate ,JDBC的多表映射学习比较)

自动控制原理之控制系统的数学模型(类比神经网络学习数学模型) 控制系统的数学模型背景建模方法常用的数学模型时域数学模型的建立建立微分方程的步骤复数域模型的建立传递函数的性质系统的典型环节及传递函数比例环节惯性环节积分环节微分环节理想微分环节一阶微分环节二阶微分环节振荡环节延时环节(时滞环节) 背景 数学模型就像是真实世界的写照,它就像一个虚拟的世界,我们可以通过建模的方式了解这个真实世界的运作规律。 这一点很像强化学习,强化学习需要一个供智能体探索、学习的环境,于是,我们通常会事先建立一个虚拟的仿真环境。举个例子,对于人类来说,可能需要经过不断地尝试,甚至是生命的代价 阅读详情

from:http://blog.zenika.com/index.php?post/2012/03/28/Presentation-de-MyBatis

Mybatis,Springjdbc,Hibernate ,JDBC的多表映射学习比较

A l’occasion de la sortie de MyBatis 3.1.0 je vous propose de découvrir cet ORM pas comme les autres. Avec un niveau d’abstraction à mi-chemin entre JDBC et JPA, le successeur d’iBatis est activement développé : plusieurs mises à jour mineures se sont succédées avant l’arrivée de la version 3.1.0.

L'ORM pas comme les autres

MyBatis est un framework de persistance de base de données relationnelles, c'est un ORM au même titre que les différentes implémentations JPA : il transforme des données issues d'une base de données relationnelles en objets Java. La différence majeure entre JPA et MyBatis, c'est que le premier opère un mapping des objets sur des tables (les entités), alors que le second ne travaille qu'avec des requêtes. JPA crée un couplage entre la base de données et le modèle objet par le biais d'annotations (ou en XML) là où MyBatis offre beaucoup de souplesse pour le mapping. Il est même possible de mapper les résultats sur des classes qu'on ne peut pas modifier (classes issues de bibliothèques tierces ou développées par une autre équipe par exemple).

Principales fonctionnalités:

  • Création de requêtes SQL dynamiques
  • Mapping avancé des résultats
  • Personnalisation du mapping
  • Gestion des transactions
  • Mise en cache des résultats
  • Pool de connexion
  • Configuration par environnement
  • Intégration à Spring et Guice

En terme d'outillage on trouve MyBatis Generator qui permet de démarrer son projet en générant des classes et des mappers de type CRUD. Un plugin Eclipse permet de faciliter l'affichage du SQL dynamique. Il existe également une version .NET de MyBatis.

Un cas d'utilisation simple

Afin d'illustrer l'utilisation de MyBatis, je vous propose de prendre un modèle de données simple en entrée, et un modèle de données différent en sortie. Le modèle en entrée est représenté par des tables dans une base de données relationnelle, et le modèle en sortie est représenté par des POJO. Entre les deux : un DAO qu'il faut implémenter pour passer de notre base de données à nos objets Java. Ajoutons comme hypothèse que les classes et l'interface ne peuvent pas être modifiées.

Base de données

public class Session {
    private Long idFormation = null;
    private String nomCours = null;
    private String nomFormateur = null;
    private Set<Participant> participants = new HashSet<>();
 
    ...
}
public class Participant {
    private Long id = null;
    private String nom = null;
 
    ...
}
public interface SessionDao {
 
    /**
     * Récupère la liste des sessions de formation auxquelles des
     * stagiaires se sont inscrits.
     */
    public List<Session> findAll();
}

Et on va se prêter à l'exercice avec du JDBC brut, JdbcTemplate, MyBatis et Hibernate. Il s'agit d'implémentationsnaïves, qui se contentent d'être correctes fonctionnellement. Les aspects tels que les best practices ou le tuning de performance ne seront donc pas abordés. Les différentes solutions sont implémentées sous la forme de tests junit et permet de s'assurer que le résultat obtenu est correct. Le code source complet est disponible à la fin de l'article.

Le résultat attendu est une liste de deux sessions, comptant trois participants chacune. D’un point de vue technique, le DAO renvoie une liste de sessions avec une relation 1-n vers des participants.

JDBC

Il s'agit là d'une API vieille de plus de 10 ans. JDBC est incontournable pour accéder à une base de données relationnelle, c'est d'ailleurs sur cette API que reposent les trois autres solutions de ce comparatif. L'ennui c'est que certaines fonctionnalités peuvent être supportées par certains drivers mais pas d'autres. Si on ajoute le fait qu'il s'agit d'une API très bas niveau, le JDBC brut n'est pas la solution à privilégier pour développer nos applications.

public class JdbcSessionDao implements SessionDao {
 
    private static final String FIND_ALL = 
            "select fo.id as id_formation, co.nom as nom_cours, fe.nom as nom_formateur, st.id as id_stagiaire, st.nom as nom_stagiaire " +
            "from formation fo, cours co, formateur fe, stagiaire st " +
            "where co.id = fo.id_cours and fe.id = fo.id_formateur and fo.id = st.id_formation " +
            "order by id_formation";
 
    @Override
    public List<Session> findAll() {
 
        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;
 
        try {
            connection = DriverManager.getConnection("jdbc:h2:mem:dataSource;DB_CLOSE_DELAY=-1", "sa", "");
            statement = connection.createStatement();
            resultSet = statement.executeQuery(FIND_ALL);
 
            Session session = null;
            List<Session> sessions = new ArrayList<>();
 
            while ( resultSet.next() ) {
                Long idFormation = resultSet.getLong("id_formation");
 
                // pour mapper la session il faut vérifier le changement d'id
                if ( isNewSession(session, idFormation) ) {
                    session = new Session();
                    session.setIdFormation(idFormation);
                    session.setNomCours( resultSet.getString("nom_cours") );
                    session.setNomFormateur( resultSet.getString("nom_formateur") );
                    sessions.add(session);
                }
 
                // dans le cas des participants pas besoin de vérifier (d'après la requête)
                Participant participant = new Participant();
                participant.setId( resultSet.getLong("id_stagiaire") );
                participant.setNom( resultSet.getString("nom_stagiaire") );
                session.getParticipants().add(participant);
            }
 
            return sessions;
        }
        catch (SQLException e) {
            throw new IllegalStateException("Echec de récupération des formations", e);
        }
        finally {
            JdbcUtils.closeResultSet(resultSet);
            JdbcUtils.closeStatement(statement);
            JdbcUtils.closeConnection(connection);
        }
    }
 
    private boolean isNewSession(Session session, Long idFormation) {
        return session == null || !session.getIdFormation().equals(idFormation);
    }
}
public class JdbcSessionDaoTest extends AbstractSessionDaoTest {
    @Test
    public void shouldFindFormationsWithPlainJdbc() throws Exception {
        checkSessions( new JdbcSessionDao().findAll() );
    }
}

La première chose qui saute aux yeux, c'est que le code fonctionnel du DAO est noyé dans le code technique. Sur les 55 lignes de code de cet extrait, seules 21 lignes ont un réel intérêt fonctionnel. La requête est dans une chaîne de caractère Java, c'est un peu gênant quand on veut la copier/coller dans un sqldeveloper par exemple. JDBC n’offre rien de ce côté là, et ce n’est pas son rôle. C’est donc au développeur de gérer une éventuelle externalisation des requêtes. Enfin, les API à manipuler ne sont pas les plus simples (ResultSet contient des dizaines de méthodes). Il n'y a donc rien de particulier à dire sur l'implémentation JDBC, si ce n'est que l'API est assez lourde à utiliser, et que l’utilisation du DriverManager n’est pas recommandée. On peut même identifier que certaines parties du code se répèteront d'un DAO à l'autre. C'est à cette problématique que répond le pattern template.

JdbcTemplate

JdbcTemplate est une classe du framework Spring qui propose de simplifier l'utilisation de JDBC en s'occupant des tâches répétitives. JdbcTemplate s'utilise en conjonction avec d'autres API (dans cet exemple l'interface RowCallbackHandler) et a vocation à s'intégrer d'une manière générale dans spring. Cet exemple a donc été implémenté dans un conteneur Spring et profite des mécanismes d'injection de dépendances.

<bean class="com.zenika.blog.mybatis.impl.jdbctemplate.JdbcTemplateSessionDao" />
public class JdbcTemplateSessionDao implements SessionDao {
 
    private static final String FIND_ALL = 
            "select fo.id as id_formation, co.nom as nom_cours, fe.nom as nom_formateur, st.id as id_stagiaire, st.nom as nom_stagiaire " +
            "from formation fo, cours co, formateur fe, stagiaire st " +
            "where co.id = fo.id_cours and fe.id = fo.id_formateur and fo.id = st.id_formation " +
            "order by id_formation";
 
    private JdbcTemplate jdbcTemplate;
 
    @Override
    public List<Session> findAll() {
        SessionRowCallbackHandler handler = new SessionRowCallbackHandler();
        jdbcTemplate.query(FIND_ALL, handler);
        return handler.getSessions();
    }
 
    @Autowired
    public void setDataSource(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }
}
class SessionRowCallbackHandler implements RowCallbackHandler {
 
    private Session session = null;
    private List<Session> sessions = new ArrayList<>();
 
    public void processRow(ResultSet resultSet) throws SQLException {
        Long idFormation = resultSet.getLong("id_formation");
 
        // pour mapper la session il faut vérifier le changement d'id
        if ( isNewSession(idFormation) ) {
            session = new Session();
            session.setIdFormation(idFormation);
            session.setNomCours( resultSet.getString("nom_cours") );
            session.setNomFormateur( resultSet.getString("nom_formateur") );
            sessions.add(session);
        }
 
        // dans le cas des participants pas besoin de vérifier (d'après la requête)
        Participant participant = new Participant();
        participant.setId( resultSet.getLong("id_stagiaire") );
        participant.setNom( resultSet.getString("nom_stagiaire") );
        session.getParticipants().add(participant);
    }
 
    private boolean isNewSession(Long idFormation) {
        return session == null || !session.getIdFormation().equals(idFormation);
    }
 
    List<Session> getSessions() {
        return sessions;
    }
}
public class JdbcTemplateSessionDaoTest extends AbstractSessionDaoTest {
    @Autowired
    SessionDao formationDao;
 
    @Test
    public void shouldFindFormationsWithJdbcTemplate() throws Exception {
        checkSessions( formationDao.findAll() );
    }
}

Premier constat, l'implémentation est découpée en deux classes, et le tout nécessite un peu de configuration. JdbcTemplate encourage une bonne séparation des responsabilités séparant le mapping du reste du traitement (que ce soit dans une classe à part ou dans une classe anonyme). En appliquant le pattern du template, les API de bas niveau ont presque disparu, seul le ResultSet subsiste, de façon quasi-anodine : on n'itère pas manuellement dessus. On ne retrouve donc dans la classe SessionRowCallbackHandler que les 21 lignes à valeur ajoutée de l’implémentation JDBC brute. La requête se trouve toujours dans une constante Java, pas d'amélioration de ce côté là. Un autre changement est visible au niveau du test, celui-ci se fait directement injecter le DAO. Le cycle de vie du DAO est donc géré par Spring tel qu'on lui a déclaré, là où l'implémentation JDBC brute devait instancier elle-même son DAO.

Comme dit précédemment, MyBatis se situe à un niveau d'abstraction entre JdbcTemplate et Hibernate. C'est donc maintenant que je vous propose de voir l'implémentation MyBatis.

MyBatis

Parmi les différents types d'ORM, on trouve les appellations micro et full. MyBatis est un micro ORM, qui se contente de faire le lien entre les mondes relationnel et objet, à la différence des implémentations JPA comme Hibernate qui sont des full ORM. En utilisant JPA, on crée tout un modèle objet à l'image des tables de la base de données (ou vice-versa). MyBatis repose sur la notion de mapper. Le mapper a pour tâche de transformer un résultat de requête en objet. C'est en substance la fonctionnalité principale du framework.

La mise en œuvre de MyBatis nécessite un peu de configuration.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="test">
        <environment id="test">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <property name="driver" value="org.h2.Driver" />
                <property name="url" value="jdbc:h2:mem:dataSource;DB_CLOSE_DELAY=-1" />
                <property name="username" value="sa" />
            </dataSource>
        </environment>
    </environments>
 
    <mappers>
        <mapper resource="formation-mapper.xml" />
    </mappers>
</configuration>

On peut ensuite implémenter notre DAO.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 
<mapper namespace="com.zenika.blog.mybatis.SessionDao">
 
    <resultMap id="SessionResultMap" type="com.zenika.blog.mybatis.Session">
        <id     property="idFormation" column="id_formation" />
        <result property="nomCours" column="nom_cours" />
        <result property="nomFormateur" column="nom_formateur" />
        <collection property="participants" resultMap="ParticipantResultMap" />
    </resultMap>
 
    <resultMap id="ParticipantResultMap" type="com.zenika.blog.mybatis.Participant">
        <id     property="id" column="id_stagiaire" />
        <result property="nom" column="nom_stagiaire" />
    </resultMap>
 
    <select id="findAll" resultMap="SessionResultMap">
        select
            fo.id as id_formation,
            co.nom as nom_cours,
            fe.nom as nom_formateur,
            st.id as id_stagiaire,
            st.nom as nom_stagiaire
        from formation fo, cours co, formateur fe, stagiaire st
        where co.id = fo.id_cours
        and fe.id = fo.id_formateur
        and fo.id = st.id_formation
    </select>
</mapper>
public class MyBatisSessionDaoTest extends AbstractSessionDaoTest {
    @Test
    public void shouldFindFormationsWithMyBatis() throws Exception {
        InputStream stream = null;
        try {
            stream = Resources.getResourceAsStream("mybatis.xml");
            SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(stream);
            SqlSession session = sessionFactory.openSession();
            checkSessions( session.getMapper(SessionDao.class).findAll() );
        }
        finally {
            IOUtils.closeSilently(stream);
        }
    }
}

Si vous êtes attentifs, vous avez remarqué que la classe implémentant SessionDao n'est pas présente. Si vous êtes très attentifs (ou que vous connaissez déjà iBatis/MyBatis) vous aurez compris que c'est MyBatis qui génère l'implémentation de l'interface. La contrepartie, c'est un fichier XML expliquant comment faire le mapping. L'XML est assez verbeux par nature, mais les mappers MyBatis restent tout à fait lisibles. La requête SQL peut être directement copiée sans avoir besoin de retirer des guillemets ou autres points-virgules! Attention par contre aux conflits entre XML et SQL sur des caractères comme < et >. On notera aussi que nous n’avons pas besoin de spécifier de clause ‘’order by’’ dans la requête, car c’est la balise <id> qui déterminera le passage à un nouvel objet. La configuration nous montre aussi qu'il existe une notion d'environnement dans MyBatis, et qu'il est capable de gérer un pool de connexion. C'est une des nombreuses fonctionnalités du framework en plus du simple mapping. Seul le test gagne en complexité, on a besoin de créer une SqlSessionFactory (une seule fois) et d'ouvrir une session afin de récupérer le Dao. Dans un conteneur comme spring, la question ne se pose pas : on peut directement se faire injecter les mappers où c'est nécessaire. Il ne reste donc plus qu'à voir l'implémentation avec Hibernate.

Hibernate

Je ne suis pas certain qu'il soit nécessaire de présenter Hibernate. C'est un full ORM qui nécessite donc de déclarer des entités correspondant aux tables de la base de données. Mon cas d'utilisation a volontairement été choisi pour afficher une des limitation des full ORM. Cela suppose donc de passer par des objets intermédiaires pour instancier les objets en sortie du DAO. Il est bien entendu possible en JPQL d'instancier directement une classe n'étant pas une entité, mais cela n'enlève pas la nécessité d'avoir des entités.

@Entity
@Table(name="formation")
public class Formation {
 
    @Id
    @Column(name="id")
    private Long id;
 
    @ManyToOne
    @JoinColumn(name="id_cours")
    private Cours cours;
 
    @ManyToOne
    @JoinColumn(name="id_formateur")
    private Formateur formateur;
 
    @Column(name="date_debut")
    private Date dateDebut;
 
    @OneToMany
    @JoinColumn(name="id_formation")
    private Set<Stagiaire> stagiaires;
 
    ...
}

Dans cet exemple nous avons besoin de créer quatre entités ne serait-ce que pour assurer le mapping. Il est faut aussi ajouter les champs que nous n'utilisons pas. On peut s'en passer pour de la lecture, mais une insertion ne fonctionnera pas si une colonne NOT NULL n'est pas mappée. Nous avons donc nos quatre entités, voyons maintenant l'implémentation.

On utilise Hibernate en tant qu'implémentation de JPA, il faut donc créer un fichier persistence.xml.

<persistence
    xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://java.sun.com/xml/ns/persistence
        http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
    version="2.0">
    <persistence-unit name="test">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <class>com.zenika.blog.mybatis.impl.jpa.Cours</class>
        <class>com.zenika.blog.mybatis.impl.jpa.Formateur</class>
        <class>com.zenika.blog.mybatis.impl.jpa.Formation</class>
        <class>com.zenika.blog.mybatis.impl.jpa.Stagiaire</class>
        <properties>
            <property name="hibernate.connection.url" value="jdbc:h2:mem:dataSource;DB_CLOSE_DELAY=-1" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"></property>
            <property name="hibernate.connection.driver_class" value="org.h2.Driver" />
            <property name="hibernate.connection.username" value="sa" />
        </properties>
    </persistence-unit>
</persistence>

On peut ensuite implémenter le DAO.

public class HibernateSessionDao implements SessionDao {
    private EntityManager entityManager;
 
    public HibernateSessionDao(EntityManager entityManager) {
        this.entityManager = entityManager;
    }
 
    @Override
    public List<Session> findAll() {
        @SuppressWarnings("unchecked")
        List<Formation> formations = entityManager.createQuery("from Formation").getResultList();
        List<Session> sessions = new ArrayList<>();
 
        for (Formation formation : formations) {
            Session session = new Session();
            session.setIdFormation( formation.getId() );
            session.setNomCours( formation.getCours().getNom() );
            session.setNomFormateur( formation.getFormateur().getNom() );
            for (Stagiaire stagiaire : formation.getStagiaires()) {
                Participant participant = new Participant();
                participant.setId( stagiaire.getId() );
                participant.setNom( stagiaire.getNom() );
                session.getParticipants().add(participant);
            }
            sessions.add(session);
        }
 
        return sessions;
    }
}
public class HibernateSessionDaoTest extends AbstractSessionDaoTest {
    @Test
    public void shouldFindFormationsWithHibernate() throws Exception {
        EntityManager entityManager = Persistence.createEntityManagerFactory("test").createEntityManager();
        checkSessions( new HibernateSessionDao(entityManager).findAll() );
    }
}

Sans surprise, le code n'est pas compliqué. Il s'agit d'une simple transformation d'objets Formation en objets Session. Comme pour le test MyBatis, il est nécessaire de créer un EntityManager, mais JPA reposant sur des conventions, le code est beaucoup moins verbeux. Il ne serait bien entendu pas nécessaire d'écrire ce code dans un conteneur Spring, EJB ou autre... Il ne faut par contre pas perdre de vue qu'il a été nécessaire de créer quatre classes afin de pouvoir implémenter le DAO ce qui fait de cette solution la plus verbeuse. D'une manière générale, ce genre de solution pousse souvent au compromis, au détriment d'une solution plus naturelle.

Attention aussi à ne pas reproduire cet exemple dans vos projets. Afin de simplifier au maximum cet exemple, Hibernate se retrouve à faire 1+3n requêtes à cause des relations. Il faut donc préciser qu’on veut charger les relations en ‘’eager loading’’ soit par annotations, ou dans la requête JPQL. Il n’est pas non plus obligatoire de passer par les entités. On peut passer par l’opérateur ‘’new’’ en JPQL pour passer directement les valeurs par le constructeur. Par contre un des postulats de départ était que les classes ‘’Session’’ et ‘’Participant’’ ne sont pas sous notre contrôle. On ne peut donc pas ajouter de constructeur. De son côté MyBatis, peut travailler aussi bien avec des setters qu’avec des constructeurs, et on peut même combiner les deux. Hibernate propose également un système de ‘’ResultTransformer’’ qui répond au besoin de mapper les résultats en direct sans passer par les entités. Cette solution est cependant spécifique à Hibernate et ne s’applique donc pas à JPA.

Pour conclure

MyBatis est un ORM très souple. En prenant le parti de se concentrer sur le mapping de résultats, MyBatis nous laisse maîtres du modèle de données sous-jacent. Il tolère de fait un changement dans la structure de la base de données, si tant est que les nouvelles requêtes renvoient les mêmes résultats. Les DBA peuvent directement modifier les requêtes avec les développeurs et n'ont pas besoin d'apprendre un langage supplémentaire (et je n'ai jamais vu de DBA optimiser une requête JPQL/Criteria!).

MyBatis offre également une meilleure abstraction :

  • puisqu'on ne manipule pas de JDBC dans la grande majorité des cas
  • que le mapping est homogène, que nos classes soient mappées ou non sur nos tables
  • qu’il offre une maîtrise du SQL exécuté
  • et qu’il écarte les pièges courants liés à une mauvaise utilisation d’un full ORM

Zenika propose désormais une formation MyBatis si vous êtes intéressé par ce framework de persistance riche et souple. A l'issue des deux jours vous connaîtrez tout le nécessaire pour bien utiliser MyBatis. La courbe d’apprentissage de ce framework est bien plus douce que celles de JDBC ou JPA, et vous garantira d’être opérationnel très rapidement.

Les sources de l'article sont téléchargeables ici.

LabVIEW Modbus TCP通信避坑指南:解决连接中断、服务器异常与自动重连问题 本文详细解析了LabVIEW环境下Modbus TCP通信的常见问题,包括连接中断、服务器异常等,并提供了自动重连机制的实现方案。通过优化错误处理、超时参数和资源管理,帮助开发者构建更稳定的工业级Modbus TCP客户端,显著提升通信可靠性。 阅读详情

相关推荐

通俗解析:霍尔编码器、光电编码器、电位计、磁编码器和旋转变压器的实战选型指南

本文深入解析了霍尔编码器、光电编码器、电位计、磁编码器和旋转变压器五大主流编码器的工作原理与核心特性。通过对比精度、环境耐受性、成本及寿命等关键维度,并结合消费电子、工业自动化、汽车电子及极端环境等典型应用场景,提供了一份清晰的实战选型指南,旨在帮助工程师根据具体需求,在性能、可靠性与成本间做出最优决策。

weixin_29216353的博客 254

JdbcTemplate查询数据 三种callback之间的区别

JdbcTemplate针对数据查询提供了多个重载的模板方法,你可以根据需要选用不同的模板方法。 如果你的查询很简单,仅仅是传入相应SQL或者相关参数,然后取得一个单一的结果,那么你可以选择如下一组便利的模板方法: int queryForInt(String sql) int queryForInt(String sql, Object[] args) long quer...

liangfeng366的专栏 470

从零到一:手把手教你用STM32和WiFi打造智能温室大棚的物联网核心

本文详细介绍了如何利用STM32单片机和WiFi技术从零构建智能温室大棚的物联网核心系统。内容涵盖硬件选型、传感器集成、低功耗WiFi通信、自动控制逻辑及OLED显示,提供实际部署中的优化技巧和故障排查方案,帮助开发者打造稳定可靠的农业自动化解决方案。

c7d8e的博客 179

JAVA实现EXCEL方法一 流的方式

    在传统行业中,很多需求在我们看来似乎是一下伪需求,但是我们很多必须要开发。     比喻EXCEL,必须要导出来,必须要和他们要求一致。     大量数据导入     根据SQL语句生成路劲的文件。       /** * 根据sql生成zip文件 * * @param sql * @param size * @param reportName * @re...

jangta的专栏 384

个人整理的数据集(手写中文数据、发票数据、快递单数据、车牌数据)

本人在工作生活中收集了各个方面比较多的真实的数据集如下: 一、手写中文数据集 1、档案类数据: 此数据集为手写档案数据,数量较大,大约128G,图像均未标注。 ex: 2、手写作文数据: 此数据集为手写作文数据,是大约800M左右,图像按行提供位置和内容标注,十分珍贵。 ex: 二、发票数据集: 1、增值税发票 此数据集包含了大量真实的增值税发票数据,大约9G,标注了发票位置数据,未提供详细标注。 ex: 2、购车发票 此数据集未提供标注。

weixin_43143224的博客 5876

计组实验5:cache大小测量与 cache line 大小测量

前言 今天做了实验5,通过 c 语言测 cache 参数。其实按理来说挺简单的,只是我们班没给代码,纯靠自己。听说别的班有给代码 emm 因为《深入理解计算机系统》这本书上面给的代码是 Linux 平台下的,而且需要一个 fcyc2 头文件,可以在 https://github.com/fabiensanglard/CpuCacheMountainViewer 这里找到。 ⚠ 我没有在 Linux 下试过课本上面的代码。。。 我是在 win10 下测试的。。。 所以 。。。 我并不确定我的代码是否正确。

AKGWSB 's blog 1万+

java持久化方式(JDBC、Mybatis、Hibernate、SpringJDBC)以及各种方式的优缺点

正常开发过程中中常见的java持久化方案(当然仅仅代表个人观点)JDBC, Mybtais (Ibatis),Hibernate ,SpringJDBC ,具体在开发的选型时该如何抉择呢?下面我们探讨一下各自方式的简单原理和优缺点JDBC 首先是JDBC,这个是Java语言提供的规范,原生操作数据库。主要就是定义一些接口和通讯类,接口定义好之后,各个数据库厂商来提供具...

辉哥的博客 2739

国密https握手协议抓包及流程详解

使用的密码套件清单-Cipher Suite,这里服务器端选择了ECC_SM4_CBC_SM3密码套件,也就是SM2公钥算法、SM4-CBC分组密码算法和SM3杂凑算法。具体来说,这里SM2算法密钥交换算法,SM4是加密算法(SM4-CBC)、SM3是校验算法(国标要求为HMAC-SM3)。服务器的加密证书:加密证书中在同样在扩展字段中KeyUsage标识出KeyEncipherment为true和dataEncipherment为true,即数字证书中包含的公钥可用来做密钥加密密钥和数据密钥。

ryanzzzzz的博客 5847

javaEE 目录(未完成)

1、hibernate,jdbc连接 Mybatis,Springjdbc,Hibernate ,JDBC的多表映射学习比较   http://blog.youkuaiyun.com/pioayang/article/details/24458317

467

蓝桥杯单片机省一经验分享1:基础篇.含详细代码与应试技巧

含详细代码、驱动修改与应试技巧

qq_53529450的博客 1万+

23、OpenMP常见用例与标准循环级示例详解

本文详细介绍了OpenMP的三种典型用例:循环级OpenMP、高级OpenMP和MPI+OpenMP,适用于不同层次的并行需求。重点讲解了循环级OpenMP在向量加法、流三元组和模板计算中的应用示例,并探讨了首次触摸优化、线程绑定、NUMA架构影响等关键性能优化策略。通过实际代码演示和性能分析,帮助开发者快速掌握OpenMP的基础并行化方法,并为后续高性能优化提供指导。

fanta的博客 87

hibernate和mybatis一对一和一对多配置

Mybaitis/hibernate学习笔记 1 Mybatis一对一,一对多配置 (1)一对一配置 1、resultMap配置 配置一对一 --> resultMap id="studentmap" type="student">     id column="sid" property="sid"[A1] >id>     result column=

翼 805

国社科基金申报书“选题与说明依据”用AI怎么写?借助Gemini 3 Pro一次理清研究演进逻辑

研究进展部分要明确指出已有研究的不足与局限,比如方法不足、数据或材料受限、研究视角单一等等局限,之后要找准研究切入点,自然引申出自己的研究问题。为提升课题申报书的质量,学术史梳理要遵循述评结合、中外结合、新老结合的原则,不仅“述”,更要“评”,兼顾国内研究与国际学术动态,统筹经典研究与最新成果。它是对选题的整体概述,需阐明研究的具体问题、视角以及核心概念。2)存在问题或争议:结合已有研究或实践现状,指出该领域在理论建构、测量工具、实践应用或研究结论方面仍存在的不足、空白或争议,明确研究的必要性;

智能AI让学术科研更容易 941

Mybatis框架-13:多表操作之多对一

第一步:建立两张表并建立外键联系 我这里是客户与订单的表进行举例 第二步:建立对应关系的映射类(domain) customer类 @Data public class Customer { private Integer cust_id; private String cust_name; private String cust_profession; ...

208

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Spring JDBC和Hibernate混用时,如何配置事务管理

由于我们项目的需求比较变态,一部分功能由于需要通过数据库配置表动态生成持久化逻辑,所以只得采用Spring JDBC,而另一部分的业务数据模型比较固定,所以我打算对这部分使用Hibernate。这样,一个应用系统同时存在Spring JDBC和Hibernate两种持久化技术。 我采用Spring 2.0,通过给注解驱动的方式进行事务管理,也就是说在Service接口中打@Tr...

stamen的程序员之路 1204

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

MyBatis中的collection两种常用使用方法(非常详细)

码云collection主要是应对表关系是一对多的情况查询的时候,用到联表去查询接下来的小案例包括市,学校,医院(随便写的),写一个最简单的demo主要的功能就是查询出所有的市以及对应的市下面所有的学校和医院实体类医院实体类学校实体类市。...

m0_67390379的博客 1544

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

框架:java数据持久化方式[jdbc,mybatis,hibernate,springjdbc]优缺点

正常开发过程中常见的java持久化方案有: jdbc,mybatis(ibatis),hibernate,springjdbc,具体在开发的选型时该如何抉择呢?下面我们来探讨一下各自方式的简单原理和优缺点。 jdbc 首先是jdbc,这是java语言提供的规范,原生操作数据库。主要就是定义一些接口和通讯类,接口定义好之后,各个数据库厂商来提供具体的实现,比如oracle,mysql等,这些...

自强不息,厚德载物。 1147

Day2——JDBC、DbUtils、JdbcTemplate、Hibernate、MyBatis持久层技术的对比

一. 知识储备

Android_la的博客 698

有了mybatis为什么spring还要jdbc

两者可以在不同的场景下使用, 小型项目 spring JDBC的性能更好,更适合管理域的sql语句, 大型项目 而mybatis则可以将sql语句批量的管理起来,还可以达到sql的重用,同时mybatis还帮你做了数据库的驱动注册加载,数据库连接的创建与销毁等数据库的管理可以让你更关注于业务,更适合在业务域使用。 ...

好奇心大爆炸 3121

Hibernate 框架总结(四):多张表的关联映射

Hibernate 框架总结(一):简单开发Hibernate 框架总结(二):session的获取方式及hibernate对象的生命周期Hibernate 框架总结(三):主键的生成策略表与表之间的关系存在三种关系一对一:丈夫——妻子, 学生——学生证一对多:学生——班级, 皇帝——大臣多对多:学生——课程, 学生——老师配置关系映射的时候,无论是什么关系,要保证你中有我,我中有你的思想一对一开...

llllllxj的博客 2652

jdbc mybatis hibernate springJDBC的一些理解

                       JDBC, Ibtais ,Hibernate ,SpringJDBC  是我们平时大家开发的过程中使用的比较多的几种持久化技术,具体在开发的过程中该怎么选择呢?            先来说说各自的特点,首先是JDBC,这个是Java语言提供的规范,主要就是定义一些接口和通讯类,接口定义好之后,各个数据库厂商来提供具体的实现,比如Oracle...

lifeneedyou的专栏 400
上一篇: oracle 存储过程 游标
下一篇: javaEE 目录(未完成)
pioayang
博客等级 码龄16年 11粉丝 48原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值