從頭開始搭建一個mybatis+postgresql平臺

    

  最近有個項目的數據庫使用postgresql,使用原生態的mybatis操做數據,原生態的沒什麼很差,只不過國內有個tk.mybatis的工具幫助咱們作了不少實用的事情,大多數狀況下咱們須要在原生態mybatis上加工的想法它基本上都已經有很好的實現,這篇將分享安裝postgresql,配置tk.mybatis的詳細步驟以及在這過程當中可能遇到的一些小問題。html

  •   安裝postgresql,執行下面的命令就能夠安裝了:          
apt-get update && apt-get install postgresql

服務端安裝好以後咱們還須要一個圖形界面的客戶端pdAdmin,我安裝的是Windows版本的postgresql自帶的,能夠到這個地址找對應的版本。安裝成功後默認會建立一個系統用戶,一個數據庫用戶,名稱以及密碼都是postgres,咱們能夠新建立用戶也能夠直接使用這個賬號,反正我這只是測試。安裝完成以後,可能會遇到遠程訪問問題:java



  遠程鏈接問題,默認狀況下只容許本地鏈接,要想容許其它客戶端鏈接,咱們能夠修改它的配置文件,這個文件的目錄位於/etc/postgresql/9.5/main,這個目錄下有兩個文件:
  1:postgresql.conf,這個是服務器相關,裏面有一個listen_address的地址,默認只監聽本地,咱們能夠修改它。git

    
  2:pg_hba.cof,這個是用戶權限相關,裏面有一個與鏈接相關的配置,能夠配置成網關模式github

    

     成功鏈接以後,大概是這個樣子,咱們能夠建立數據庫,表等對象。spring

 

  •   mybatis代碼生成器,數據庫與Model的映射,這類機械的工做應該交給機器來完成,詳細使用參考這裏
  •   通用mapper,單表的CRUD操做能夠抽像出一個公共接口,tk.mybatis提供的通用mapper能夠幫助咱們解決這類問題。
    • mapper.xml,足夠小(只包含字段映射)
<mapper namespace="com.jim.logstashmvc.dao.generated.mapper.ProductMapper">
  <resultMap id="BaseResultMap" type="com.jim.logstashmvc.dao.generated.entity.Product">
    <!--
      WARNING - @mbggenerated
    -->
    <id column="id" jdbcType="BIGINT" property="id" />
    <result column="name" jdbcType="VARCHAR" property="name" />
  </resultMap>
</mapper>
    • mapper,足夠簡單(只須要繼承經過mapper接口)
public interface ProductMapper extends Mapper<Product> {
}
  •   插件,這裏有分頁插件,SQL性能分析插件等,與mybatis集成很是容易。

  


  如何與spring集成?sql

  • 生成器的集成,能夠採用maven方式來運行代碼生成器
    • 依賴的包
<!-- MyBatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>${mybatis.version}</version>
        </dependency>

        <!-- Spring集成 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>${mybatis.spring.version}</version>
        </dependency>

        <!-- MBG -->
        <dependency>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-core</artifactId>
            <version>${MBG.version}</version>
            <scope>compile</scope>
            <optional>true</optional>
        </dependency>

        <!-- 分頁 -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>${pagehelper.version}</version>
        </dependency>

        <!-- 通用Mapper -->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper</artifactId>
            <version>${mapper.version}</version>
        </dependency>

        <!-- TkMybatis 會使用到JPA的註解 -->
        <dependency>
            <groupId>javax.persistence</groupId>
            <artifactId>persistence-api</artifactId>
            <version>1.0</version>
        </dependency>

        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>9.3-1102-jdbc41</version>
        </dependency>
    •  配置生成器插件,指定配置文件路徑,配置依賴:一個是數據庫驅動,一個是通用mapper
<!--MBG-->
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>${MBG.version}</version>
                <configuration>
                    <configurationFile>${basedir}/src/main/resources/generator/generatorConfig.xml</configurationFile>
                    <overwrite>true</overwrite>
                    <verbose>true</verbose>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.postgresql</groupId>
                        <artifactId>postgresql</artifactId>
                        <version>9.3-1102-jdbc41</version>
                    </dependency>

                    <dependency>
                        <groupId>tk.mybatis</groupId>
                        <artifactId>mapper</artifactId>
                        <version>${mapper.version}</version>
                    </dependency>

                </dependencies>
            </plugin>
  •   生成器配置文件
    •  配置數據庫鏈接
    •  配置生成的model,mapper以及mapper.xml的存放路徑
    •  配置須要生成的表信息

          注意下targetRuntime,這裏採用的是MyBatis3Simple,它的默認選項是MyBatis3。若是採用通用mapper,咱們在spring掃描接口時能夠這樣寫。
  數據庫

 <bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="jimSqlSessionFactory"/>
        <property name="basePackage" value="com.jim.logstashmvc.dao.generated.mapper"/>
    </bean>

        若是是MyBatis3,生成的mapper.xml格式會複雜不少,我以前遇到過這樣的問題:使用MyBatis3生成的mapper.xml而後錯誤 的配置了MapperScannerConfigurer爲下面通用mapper模式,提示個人錯誤以下,緣由能夠認定是配置問題(不是某個mapper.xml中的id重複問題) ,後續再研究下非通用mapper的配置。apache

Caused by: java.lang.IllegalArgumentException: Mapped Statements collection already contains value for com.jim.logstashmvc.dao.generated.mapper.ProductMapper.selectByExample
at org.apache.ibatis.session.Configuration$StrictMap.put(Configuration.java:837)
at org.apache.ibatis.session.Configuration$StrictMap.put(Configuration.java:809)

 

  上面的報錯信息已經找到,緣由是由於採用了MyBatis3方式生成Mapper,但同時在配置文件中錯誤的增長了通用Mapper的插件,它會在Mapper接口上增長一個Mapper<T>的繼承,而一旦繼承了這個經過接口,它裏面包含的方法Id與MyBatis3生成的方法Id正好重複,致使了在編譯時提示上面的錯誤。api

 

   使用了通用Mapper以後,有個缺點就是使用Example時沒有強類型的方法了,好比不能這樣:服務器

        ProductExample example =new ProductExample();
        ProductExample.Criteria criteria=example.createCriteria();
        if (product.getId() != null) {
            criteria.andIdEqualTo(product.getId());
        }

  而只能這樣寫,字段名稱須要以字符串的形式進行指定。這種方式很是適合於動態構建查詢,好比:列表頁的動態條件搜索

        Example example = new Example(Product.class);
        Example.Criteria criteria = example.createCriteria();
        if (product.getId() != null) {
            criteria.andEqualTo("id", product.getId());
        }

     咱們以前的項目爲了可以使用動態條件構建,又想使用強類型的Example進行簡單的查詢,咱們擴展了targetRuntime,讓其生成的Mapper即繼承自Map<T>又生成了具體的方法,只不過生成的具體方法在名稱上作了調整,在名稱中間增長了一個獨有的佔有符,默認MBG生成的查詢方法名稱是selectByExample,這裏咱們另外生成一個selectByConcreteExample。這樣作也是有代價的,生成的mapper.xml也再也不只包含實體映射,mapper接口也再也不只是繼承的近似空接口了,具體怎麼用仁者見仁吧。

public interface ImageMapper extends PartyInterface, RowBoundsMapper<Image>, BaseMapper<Image>, ExampleMapper<Image> {
    int countByConcreteExample(ImageExample example);

    int deleteByConcreteExample(ImageExample example);

    List<Image> selectByConcreteExample(ImageExample example);

    int updateByConcreteExampleSelective(@Param("record") Image record, @Param("example") ImageExample example);

    int updateByConcreteExample(@Param("record") Image record, @Param("example") ImageExample example);
}

 

     生成器的配置詳細以下:

<generatorConfiguration>
    <properties resource="config.properties"/>
    <context id="jim" targetRuntime="MyBatis3Simple" defaultModelType="flat">
        <property name="beginningDelimiter" value="`"/>
        <property name="endingDelimiter" value="`"/>
        <plugin type="${mapper.plugin}">
            <property name="mappers" value="${mapper.Mapper}"/>
        </plugin>
        <jdbcConnection driverClass="${jdbc.driverClass}"
                        connectionURL="${jdbc.url}"
                        userId="${jdbc.username}"
                        password="${jdbc.password}">
        </jdbcConnection>
        <javaModelGenerator targetPackage="${targetModelPackage}"
                            targetProject="${targetJavaProject}"/>
        <sqlMapGenerator targetPackage="mapper" targetProject="${targetResourcesProject}"/>
        <javaClientGenerator targetPackage="${targetMapperPackage}"
                             targetProject="${targetJavaProject}"
                             type="XMLMAPPER">
        </javaClientGenerator>
        <table tableName="product" domainObjectName="Product"></table>
    </context>
</generatorConfiguration>
  •  配置maven運行參數,以下圖所示便可。

       

 

  • mybatis的集成,主要是配置鏈接池信息,插件,mapper掃描等信息。
<bean id="jimDataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="${jdbc.driverClass}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>

        <property name="initialSize" value="5"/>
        <property name="minIdle" value="10"/>
        <property name="maxWait" value="60000"/>
        <property name="timeBetweenEvictionRunsMillis" value="60000"/>
        <property name="minEvictableIdleTimeMillis" value="3600000"/>
        <property name="validationQuery" value="SELECT 1"/>
        <property name="testWhileIdle" value="true"/>
        <property name="testOnBorrow" value="false"/>
        <property name="testOnReturn" value="false"/>
    </bean>

    <bean id="jimSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="jimDataSource"/>
        <property name="mapperLocations" value="classpath:mapper/*.xml"/>
        <property name="typeAliasesPackage" value="com.jim.logstashmvc.dao.generated.entity"/>
        <property name="plugins">
            <array>
                <bean class="com.github.pagehelper.PageHelper">
                    <property name="properties">
                        <value>
                        dialect=postgresql
                        reasonable=true
                        supportMethodsArguments=true
                        returnPageInfo=check
                        params=count=countSql
                    </value>

                    </property>
                </bean>
            </array>
        </property>

    </bean>

    <bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="jimSqlSessionFactory"/>
        <property name="basePackage" value="com.jim.logstashmvc.dao.generated.mapper"/>
    </bean>
  •   通用mapper的用法:
    •  mapper,全部生成的mapper就繼承於Mapper<T>,默認持有通用mapper全部接口,包含CRUD常見操做
    •  IService,通用mapper接口的定義,咱們能夠根據本身的業務修改此接口
@Service
public interface IService<T> {

    T selectByKey(Object key);

    int save(T entity);

    int delete(Object key);

    int updateAll(T entity);

    int updateNotNull(T entity);

    List<T> selectByExample(Object example);

    //TODO 其餘...
}
    •  BaseService,通用mapper的實現類
public abstract class BaseService<T> implements IService<T> {

    @Autowired
    protected Mapper<T> mapper;

    public Mapper<T> getMapper() {
        return mapper;
    }

    @Override
    public T selectByKey(Object key) {
        return mapper.selectByPrimaryKey(key);
    }

    public int save(T entity) {
        return mapper.insert(entity);
    }

    public int delete(Object key) {
        return mapper.deleteByPrimaryKey(key);
    }

    public int updateAll(T entity) {
        return mapper.updateByPrimaryKey(entity);
    }

    public int updateNotNull(T entity) {
        return mapper.updateByPrimaryKeySelective(entity);
    }

    public List<T> selectByExample(Object example) {
        return mapper.selectByExample(example);
    }

    //TODO 其餘...
}
    •   具體服務類
@Service
public class ProductServiceImpl extends BaseService<Product> implements ProductService {
    @Override
    public List<Product> selectByProduct(Product product, int page, int rows) {
        Example example = new Example(Product.class);
        Example.Criteria criteria = example.createCriteria();
        if(!StringUtils.isBlank(product.getName())){
            criteria.andEqualTo("name",product.getName());
        }
        if (product.getId() != null) {
            criteria.andEqualTo("id", product.getId());
        }
        PageHelper.startPage(page, rows);
        return selectByExample(example);

    }

}

 

 

安裝postgresql而且成功遠程鏈接,集成MBG生成mapper以及model,而後將mybatis與spring集成,最後經過通用mapper中聯起來就達到了咱們的目的:經過少許的代碼完成大部分的工做,重複勞動交給工具完成。但通用mapper有它的優勢也就有它的缺點,須要根據項目環境來平衡,我的感受利大於弊。

 

   本文引用:   1:http://www.mybatis.tk/   2:https://github.com/abel533/Mybatis-Spring

相關文章
相關標籤/搜索