• Spring整合MongoDB(转)


    1.认识Spring Data MongoDB


            之前还的确不知道Spring连集成Nosql的东西都实现了,还以为自己又要手动封装一个操作MongoDB的API呢,结果就发现了Spring Data MongoDB。不愧是Spring,真是给了我们春天,佩服的渣渣我目瞪狗呆……

            废话少说,看招。Spring Data其实是一个高级别的Spring Source项目,而Spring Data MongoDB仅仅是其中的一个子项目。Spring Data旨在为关系型数据库、非关系型数据、Map-Reduce框架、云数据服务等等提供统一的数据访问API。
            无论是哪种持久化存储, 数据访问对象(或称作为DAO,即Data Access Objects)通常都会提供对单一域对象的CRUD (创建、读取、更新、删除)操作、查询方法、排序和分页方法等。Spring Data则提供了基于这些层面的统一接口(CrudRepository,PagingAndSortingRepository)以及对持久化存储的实现。

    Spring Data 包含多个子项目:

    Commons - 提供共享的基础框架,适合各个子项目使用,支持跨数据库持久化
    Hadoop - 基于 Spring 的 Hadoop 作业配置和一个 POJO 编程模型的 MapReduce 作业
    Key-Value  - 集成了 Redis 和 Riak ,提供多个常用场景下的简单封装
    Document - 集成文档数据库:CouchDB 和 MongoDB 并提供基本的配置映射和资料库支持
    Graph - 集成 Neo4j 提供强大的基于 POJO 的编程模型
    Graph Roo AddOn - Roo support for Neo4j
    JDBC Extensions - 支持 Oracle RAD、高级队列和高级数据类型
    JPA - 简化创建 JPA 数据访问层和跨存储的持久层功能
    Mapping - 基于 Grails 的提供对象映射框架,支持不同的数据库
    Examples - 示例程序、文档和图数据库
    Guidance - 高级文档
    2. HelloWorld

    好了,说了这么多,还是用代码表现最为实在,老规矩,Hello World,我这里创建了一个Maven Java项目demo。
    2.1 配置依赖

    【pom.xml】

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
     
        <groupId>com.jastar</groupId>
        <artifactId>demo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <packaging>jar</packaging>
     
        <name>demo</name>
        <url>http://www.jastar-wang.tech</url>
     
        <!-- 版本配置 -->
        <properties>
            <spring.version>4.1.4.RELEASE</spring.version>
            <spring.data.version>1.7.0.RELEASE</spring.data.version>
            <log4j.version>1.2.17</log4j.version>
        </properties>
     
        <dependencies>
            <!-- 单元测试包 -->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.10</version>
                <scope>test</scope>
            </dependency>
     
            <!-- spring核心包 -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-beans</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-tx</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-webmvc</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aop</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-test</artifactId>
                <version>${spring.version}</version>
            </dependency>
     
            <!-- 关系型数据库整合时需配置 如hibernate jpa等 -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-orm</artifactId>
                <version>${spring.version}</version>
            </dependency>
     
            <!-- spring aop 关联 -->
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjweaver</artifactId>
                <version>1.8.7</version>
            </dependency>
     
            <!-- log4j -->
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>${log4j.version}</version>
            </dependency>
     
            <!-- spring整合MongoDB -->
            <dependency>
                <groupId>org.springframework.data</groupId>
                <artifactId>spring-data-mongodb</artifactId>
                <version>${spring.data.version}</version>
            </dependency>
     
        </dependencies>
     
        <repositories>
            <repository>
                <id>spring-milestone</id>
                <name>Spring Maven MILESTONE Repository</name>
                <url>http://repo.spring.io/libs-milestone</url>
            </repository>
        </repositories>
     
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <configuration>
                        <source>1.7</source>
                        <target>1.7</target>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </project>
    注意:这里我使用的是Spring Data MongoDB 1.7.0版本,截止当前发文时间最新稳定版本应该是1.10.1

    2.2 映射实体类

    【UserInfo.java】
    package com.jastar.demo.entity;
     
    import java.io.Serializable;
    import java.sql.Timestamp;
     
    import org.springframework.data.annotation.Id;
    import org.springframework.data.mongodb.core.index.IndexDirection;
    import org.springframework.data.mongodb.core.index.Indexed;
    import org.springframework.data.mongodb.core.mapping.Document;
    import org.springframework.data.mongodb.core.mapping.Field;
     
    /**
     * 用户实体类
     * <p>
     * ClassName: UserInfo
     * </p>
     * <p>
     * Description:本类用来展示MongoDB实体类映射的使用
     * </p>
     * <p>
     * Copyright: (c)2017 Jastar·Wang,All rights reserved.
     * </p>
     * 
     * @author Jastar·Wang
     * @date 2017年4月12日
     */
    @Document(collection = "coll_user")
    public class UserInfo implements Serializable {
     
        /** serialVersionUID */
        private static final long serialVersionUID = 1L;
     
        // 主键使用此注解
        @Id
        private String id;
     
        // 字段使用此注解
        @Field
        private String name;
     
        // 字段还可以用自定义名称
        @Field("myage")
        private int age;
     
        // 还可以生成索引
        @Indexed(name = "index_birth", direction = IndexDirection.DESCENDING)
        @Field
        private Timestamp birth;
     
        public String getId() {
            return id;
        }
     
        public void setId(String id) {
            this.id = id;
        }
     
        public String getName() {
            return name;
        }
     
        public void setName(String name) {
            this.name = name;
        }
     
        public int getAge() {
            return age;
        }
     
        public void setAge(int age) {
            this.age = age;
        }
     
        public Timestamp getBirth() {
            return birth;
        }
     
        public void setBirth(Timestamp birth) {
            this.birth = birth;
        }
     
    }

    附录:
    @Id - 用于字段级别,标记这个字段是一个主键,默认生成的名称是“_id”

    @Document - 用于类,以表示这个类需要映射到数据库,您也可以指定映射到数据库的集合名称

    @DBRef - 用于字段,以表示它将使用com.mongodb.DBRef进行存储。

    @Indexed - 用于字段,表示该字段需要如何创建索引

    @CompoundIndex - 用于类,以声明复合索引

    @GeoSpatialIndexed - 用于字段,进行地理位置索引

    @TextIndexed - 用于字段,标记该字段要包含在文本索引中

    @Language - 用于字段,以设置文本索引的语言覆盖属性。

    @Transient - 默认情况下,所有私有字段都映射到文档,此注解将会去除此字段的映射

    @PersistenceConstructor - 标记一个给定的构造函数,即使是一个protected修饰的,在从数据库实例化对象时使用。构造函数参数通过名称映射到检索的DBObject中的键值。

    @Value - 这个注解是Spring框架的一部分。在映射框架内,它可以应用于构造函数参数。这允许您使用Spring表达式语言语句来转换在数据库中检索的键值,然后再用它来构造一个域对象。为了引用给定文档的属性,必须使用以下表达式:@Value("#root.myProperty"),root要指向给定文档的根。

    @Field - 用于字段,并描述字段的名称,因为它将在MongoDB BSON文档中表示,允许名称与该类的字段名不同。

    @Version - 用于字段锁定,保存操作时检查修改。初始值是0,每次更新时自动触发。

    2.3 整合配置

    【db.properties】

    ###---The mongodb settings---
    mongo.dbname=demo
    mongo.host=localhost
    mongo.port=27017
    mongo.connectionsPerHost=8
    mongo.threadsAllowedToBlockForConnectionMultiplier=4
    mongo.connectTimeout=1000
    mongo.maxWaitTime=1500
    mongo.autoConnectRetry=true
    mongo.socketKeepAlive=true
    mongo.socketTimeout=1500
    mongo.slaveOk=true
    mongo.writeNumber=1
    mongo.writeTimeout=0
    mongo.writeFsync=true

    【spring-mgo.xml】

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:mongo="http://www.springframework.org/schema/data/mongo"
        xsi:schemaLocation="http://www.springframework.org/schema/context
              http://www.springframework.org/schema/context/spring-context-3.0.xsd
              http://www.springframework.org/schema/data/mongo 
              http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd
              http://www.springframework.org/schema/beans
              http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
     
        <!-- 读取属性文件 -->
        <context:property-placeholder location="classpath:db.properties" />
     
        <!-- 启用注解支持 -->
        <context:annotation-config />
     
        <!-- 扫描组件包 -->
        <context:component-scan base-package="com.jastar.demo" />
     
        <!-- SpringData类型转换器 -->
        <mongo:mapping-converter id="mongoConverter">
            <mongo:custom-converters>
                <mongo:converter>
                    <bean class="com.jastar.demo.converter.TimestampConverter" />
                </mongo:converter>
            </mongo:custom-converters>
        </mongo:mapping-converter>
     
        <!-- 
            MongoDB配置部分 
            1.mongo:连接配置 
            2.db-factory:相当于sessionFactory 
            3.mongoTemplate:与数据库接口交互的主要实现类 
        -->
        <mongo:mongo host="${mongo.host}" port="${mongo.port}">
            <mongo:options 
                connections-per-host="${mongo.connectionsPerHost}"
                threads-allowed-to-block-for-connection-multiplier="${mongo.threadsAllowedToBlockForConnectionMultiplier}"
                connect-timeout="${mongo.connectTimeout}" 
                max-wait-time="${mongo.maxWaitTime}"
                auto-connect-retry="${mongo.autoConnectRetry}" 
                socket-keep-alive="${mongo.socketKeepAlive}"
                socket-timeout="${mongo.socketTimeout}" 
                slave-ok="${mongo.slaveOk}"
                write-number="${mongo.writeNumber}" 
                write-timeout="${mongo.writeTimeout}"
                write-fsync="${mongo.writeFsync}" />
        </mongo:mongo>
     
        <mongo:db-factory id="mongoDbFactory" dbname="${mongo.dbname}" mongo-ref="mongo" />
     
        <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
            <constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
            <constructor-arg name="mongoConverter" ref="mongoConverter" />
        </bean>
     
    </beans>

    说明:
    mongo:options - 用于配置一些数据库连接设置信息
    mongo:db-factory - 相当于Hibernate中的SessionFactory
    mongoTemplate - 非常重要,整个与数据库的交互操作全是靠他,相当于Hibernate的HibernateTemplate

            另外,以上配置中有一个类型转换器,因为Spring Data MongoDB本身默认时间类型是java.util.Date,如果实体字段含有java.sql.Timestamp类型,需要自定义转换器进行转换,否则后续操作会报错(深有感触)!什么?不把转换器代码贴出来?别着急,文章最后有整个项目地址,去里面找吧……偷笑.GIF

    2.4 Dao层参考实现

    【BaseDaoImpl.java】

    package com.jastar.demo.dao.impl;
     
    import static org.springframework.data.mongodb.core.query.Criteria.where;
     
    import java.io.Serializable;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.lang.reflect.Modifier;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
     
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.annotation.Id;
    import org.springframework.data.domain.Sort;
    import org.springframework.data.domain.Sort.Direction;
    import org.springframework.data.domain.Sort.Order;
    import org.springframework.data.mongodb.core.MongoTemplate;
    import org.springframework.data.mongodb.core.query.Query;
    import org.springframework.data.mongodb.core.query.Update;
     
    import com.jastar.demo.dao.IBaseDao;
    import com.jastar.demo.util.EmptyUtil;
    import com.jastar.demo.util.PageModel;
     
    /**
     * 基本操作接口MongoDB数据库实现类
     * <p>
     * ClassName: BaseDaoImpl
     * </p>
     * <p>
     * Description:本实现类适用于MongoDB数据库,以下代码仅供参考,本人水平有限,可能会存在些许问题(如有更好方案可告知我,一定虚心学习),
     * 再次提醒,仅供参考!!
     * </p>
     * <p>
     * Copyright: (c)2017 Jastar·Wang,All rights reserved.
     * </p>
     * 
     * @author Jastar·Wang
     * @date 2017年4月12日
     */
    public abstract class BaseDaoImpl<T> implements IBaseDao<T> {
     
        protected abstract Class<T> getEntityClass();
     
        @Autowired
        protected MongoTemplate mgt;
     
        @Override
        public void save(T entity) {
            mgt.save(entity);
        }
     
        @Override
        public void update(T entity) {
     
            // 反向解析对象
            Map<String, Object> map = null;
            try {
                map = parseEntity(entity);
            } catch (Exception e) {
                e.printStackTrace();
            }
     
            // ID字段
            String idName = null;
            Object idValue = null;
     
            // 生成参数
            Update update = new Update();
            if (EmptyUtil.isNotEmpty(map)) {
                for (String key : map.keySet()) {
                    if (key.indexOf("{") != -1) {
                        // 设置ID
                        idName = key.substring(key.indexOf("{") + 1, key.indexOf("}"));
                        idValue = map.get(key);
                    } else {
                        update.set(key, map.get(key));
                    }
                }
            }
            mgt.updateFirst(new Query().addCriteria(where(idName).is(idValue)), update, getEntityClass());
        }
     
        @Override
        public void delete(Serializable... ids) {
            if (EmptyUtil.isNotEmpty(ids)) {
                for (Serializable id : ids) {
                    mgt.remove(mgt.findById(id, getEntityClass()));
                }
            }
     
        }
     
        @Override
        public T find(Serializable id) {
            return mgt.findById(id, getEntityClass());
        }
     
        @Override
        public List<T> findAll() {
            return mgt.findAll(getEntityClass());
        }
     
        @Override
        public List<T> findAll(String order) {
            List<Order> orderList = parseOrder(order);
            if (EmptyUtil.isEmpty(orderList)) {
                return findAll();
            }
            return mgt.find(new Query().with(new Sort(orderList)), getEntityClass());
        }
     
        @Override
        public List<T> findByProp(String propName, Object propValue) {
            return findByProp(propName, propValue, null);
        }
     
        @Override
        public List<T> findByProp(String propName, Object propValue, String order) {
            Query query = new Query();
            // 参数
            query.addCriteria(where(propName).is(propValue));
            // 排序
            List<Order> orderList = parseOrder(order);
            if (EmptyUtil.isNotEmpty(orderList)) {
                query.with(new Sort(orderList));
            }
            return mgt.find(query, getEntityClass());
        }
     
        @Override
        public List<T> findByProps(String[] propName, Object[] propValue) {
            return findByProps(propName, propValue, null);
        }
     
        @Override
        public List<T> findByProps(String[] propName, Object[] propValue, String order) {
            Query query = createQuery(propName, propValue, order);
            return mgt.find(query, getEntityClass());
        }
     
        @Override
        public T uniqueByProp(String propName, Object propValue) {
            return mgt.findOne(new Query(where(propName).is(propValue)), getEntityClass());
        }
     
        @Override
        public T uniqueByProps(String[] propName, Object[] propValue) {
            Query query = createQuery(propName, propValue, null);
            return mgt.findOne(query, getEntityClass());
        }
     
        @Override
        public PageModel<T> pageAll(int pageNo, int pageSize) {
            return pageAll(pageNo, pageSize, null);
        }
     
        @Override
        public PageModel<T> pageAll(int pageNo, int pageSize, String order) {
            return pageByProp(pageNo, pageSize, null, null, order);
        }
     
        @Override
        public PageModel<T> pageByProp(int pageNo, int pageSize, String param, Object value) {
            return pageByProp(pageNo, pageSize, param, value, null);
        }
     
        @Override
        public PageModel<T> pageByProp(int pageNo, int pageSize, String param, Object value, String order) {
            String[] params = null;
            Object[] values = null;
            if (EmptyUtil.isNotEmpty(param)) {
                params = new String[] { param };
                values = new Object[] { value };
            }
            return pageByProps(pageNo, pageSize, params, values, order);
        }
     
        @Override
        public PageModel<T> pageByProps(int pageNo, int pageSize, String[] params, Object[] values) {
            return pageByProps(pageNo, pageSize, params, values, null);
        }
     
        @Override
        public PageModel<T> pageByProps(int pageNo, int pageSize, String[] params, Object[] values, String order) {
            // 创建分页模型对象
            PageModel<T> page = new PageModel<>(pageNo, pageSize);
     
            // 查询总记录数
            int count = countByCondition(params, values);
            page.setTotalCount(count);
     
            // 查询数据列表
            Query query = createQuery(params, values, order);
     
            // 设置分页信息
            query.skip(page.getFirstResult());
            query.limit(page.getPageSize());
     
            // 封装结果数据
            page.setList(mgt.find(query, getEntityClass()));
     
            return page;
        }
     
        @Override
        public int countByCondition(String[] params, Object[] values) {
            Query query = createQuery(params, values, null);
            Long count = mgt.count(query, getEntityClass());
            return count.intValue();
        }
     
        /**
         * 创建带有where条件(只支持等值)和排序的Query对象
         * 
         * @param params
         *            参数数组
         * @param values
         *            参数值数组
         * @param order
         *            排序
         * @return Query对象
         */
        protected Query createQuery(String[] params, Object[] values, String order) {
            Query query = new Query();
     
            // where 条件
            if (EmptyUtil.isNotEmpty(params) && EmptyUtil.isNotEmpty(values)) {
                for (int i = 0; i < params.length; i++) {
                    query.addCriteria(where(params[i]).is(values[i]));
                }
            }
     
            // 排序
            List<Order> orderList = parseOrder(order);
            if (EmptyUtil.isNotEmpty(orderList)) {
                query.with(new Sort(orderList));
            }
     
            return query;
        }
     
        /**
         * 解析Order字符串为所需参数
         * 
         * @param order
         *            排序参数,如[id]、[id asc]、[id asc,name desc]
         * @return Order对象集合
         */
        protected List<Order> parseOrder(String order) {
            List<Order> list = null;
            if (EmptyUtil.isNotEmpty(order)) {
                list = new ArrayList<Order>();
                // 共有几组排序字段
                String[] fields = order.split(",");
                Order o = null;
                String[] item = null;
                for (int i = 0; i < fields.length; i++) {
                    if (EmptyUtil.isEmpty(fields[i])) {
                        continue;
                    }
                    item = fields[i].split(" ");
                    if (item.length == 1) {
                        o = new Order(Direction.ASC, item[0]);
                    } else if (item.length == 2) {
                        o = new Order("desc".equalsIgnoreCase(item[1]) ? Direction.DESC : Direction.ASC, item[0]);
                    } else {
                        throw new RuntimeException("排序字段参数解析出错");
                    }
                    list.add(o);
                }
            }
            return list;
        }
     
        /**
         * 将对象的字段及值反射解析为Map对象<br>
         * 这里使用Java反射机制手动解析,并且可以识别注解为主键的字段,以达到根据id进行更新实体的目的<br>
         * key:字段名称,value:字段对应的值
         * 
         * @param t
         *            要修改的对象
         * @return Map对象,注意:id字段的key封装为“{id字段名称}”,以供后续识别
         * @throws Exception
         */
        protected Map<String, Object> parseEntity(T t) throws Exception {
            Map<String, Object> map = new HashMap<String, Object>();
            /*
             * 解析ID
             */
            String idName = "";
            Field[] declaredFields = getEntityClass().getDeclaredFields();
            for (Field field : declaredFields) {
                if (field.isAnnotationPresent(Id.class)) {
                    field.setAccessible(true);
                    map.put("{" + field.getName() + "}", field.get(t));
                    idName = field.getName();
                    break;
                }
            }
            /*
             * 解析其他属性
             */
            Method[] methods = getEntityClass().getDeclaredMethods();
            if (EmptyUtil.isNotEmpty(methods)) {
                for (Method method : methods) {
                    if (method.getName().startsWith("get") && method.getModifiers() == Modifier.PUBLIC) {
                        String fieldName = parse2FieldName(method.getName());
                        if (!fieldName.equals(idName)) {
                            map.put(fieldName, method.invoke(t));
                        }
                    }
                }
            }
     
            return map;
        }
     
        /**
         * 将get方法名转换为对应的字段名称
         * 
         * @param methodName
         *            如:getName
         * @return 如:name
         */
        private String parse2FieldName(String methodName) {
            String name = methodName.replace("get", "");
            name = name.substring(0, 1).toLowerCase() + name.substring(1);
            return name;
        }
     
    }
    View Code

    说明:

            以上实现仅供参考某些实现点,mongoTemplate如何使用还要自己去详细的摸索,我也没办法,毕竟我也这样过来的,大多数方法都已经提供了,只是update方法不像关系型数据库那样,给个实体类就能更新,需要自己去想办法搞定。

     【TestUseService.java】

    package com.jastar.test;
     
    import java.sql.Timestamp;
    import java.util.List;
     
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
     
    import com.jastar.demo.entity.UserInfo;
    import com.jastar.demo.service.UserService;
    import com.jastar.demo.util.PageModel;
     
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = "classpath:spring-mgo.xml")
    public class TestUserService {
     
        @Autowired
        private UserService service;
     
        @Test
        public void save() {
            UserInfo user = new UserInfo();
            user.setName("张三");
            user.setAge(25);
            user.setBirth(Timestamp.valueOf("2017-4-12 16:52:00"));
            service.save(user);
            System.out.println("已生成ID:" + user.getId());
        }
     
        @Test
        public void find() {
            UserInfo user = service.find("58edf1b26f033406394a8a61");
            System.out.println(user.getName());
        }
     
        @Test
        public void update() {
            UserInfo user = service.find("58edf1b26f033406394a8a61");
            user.setAge(18);
            service.update(user);
        }
     
        @Test
        public void delete() {
            service.delete("58edef886f03c7b0fdba51b9");
        }
     
        @Test
        public void findAll() {
            List<UserInfo> list = service.findAll("age desc");
            for (UserInfo u : list) {
                System.out.println(u.getName());
            }
        }
     
        @Test
        public void findByProp() {
            List<UserInfo> list = service.findByProp("name", "张三");
            for (UserInfo u : list) {
                System.out.println(u.getName());
            }
        }
     
        @Test
        public void findByProps() {
            List<UserInfo> list = service.findByProps(new String[] { "name", "age" }, new Object[] { "张三", 18 });
            for (UserInfo u : list) {
                System.out.println(u.getName());
            }
        }
     
        @Test
        public void pageAll() {
            PageModel<UserInfo> page = service.pageAll(1, 10);
            System.out.println("总记录:" + page.getTotalCount() + ",总页数:" + page.getTotalPage());
            for (UserInfo u : page.getList()) {
                System.out.println(u.getName());
            }
        }
     
        @Test
        public void pageByProp() {
            PageModel<UserInfo> page = service.pageByProp(1, 10, "name", "张三");
            System.out.println("总记录:" + page.getTotalCount() + ",总页数:" + page.getTotalPage());
            for (UserInfo u : page.getList()) {
                System.out.println(u.getName());
            }
        }
     
    }

    ————————————————
    版权声明:本文为CSDN博主「代码与酒」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/qq_16313365/article/details/70142729

  • 相关阅读:
    亲们,知道你想更优秀,你做到这些了吗?
    Linux socket编程学习笔记(一):socket()函数详解
    关于typedef的用法总结
    c,c++里面,头文件里面的ifndef /define/endif的作用
    玩转ptrace
    文笔流畅,修辞得体
    定义和实现一个类的成员函数为回调函数
    《Shell 脚本学习指南 》 背景知识与入门 [第一、二章]
    使用ptrace跟踪进程
    FCKeditor 2.6.4.1配置
  • 原文地址:https://www.cnblogs.com/muxi0407/p/11750435.html
Copyright © 2020-2023  润新知