Rumah > Java > javaTutorial > Bagaimana untuk menulis rangka kerja lapisan kegigihan dalam Java

Bagaimana untuk menulis rangka kerja lapisan kegigihan dalam Java

PHPz
Lepaskan: 2023-04-18 19:37:38
ke hadapan
1339 orang telah melayarinya

Semakan operasi dan analisis masalah JDBC

Pelajar yang mempelajari Java pasti telah didedahkan dengan jdbc Mari kita semak operasi jdbc yang kita hadapi semasa tempoh pemula

Berikut. kod menyambung ke pangkalan data untuk menanyakan pengguna Maklumat jadual, medan jadual pengguna ialah id pengguna dan nama pengguna nama pengguna masing-masing.

Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        User user = new User();
        try {
            // 加载数据库驱动
            //Class.forName("com.mysql.jdbc.Driver");
            Class.forName("com.mysql.cj.jdbc.Driver");
            // 通过驱动管理类获取数据库链接
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8", "root", "mimashi3124");
            // 定义sql语句?表示占位符
            String sql = "select * from user where username = ?";
            // 获取预处理statement
            preparedStatement = connection.prepareStatement(sql);
            // 设置参数,第⼀个参数为sql语句中参数的序号(从1开始),第⼆个参数为设置的参数值
            preparedStatement.setString(1, "盖伦");
            // 向数据库发出sql执⾏查询,查询出结果集
            resultSet = preparedStatement.executeQuery();
            // 遍历查询结果集
            while (resultSet.next()) {
                int id = resultSet.getInt("id");
                String username = resultSet.getString("username");
                // 封装User
                user.setId(id);
                user.setUsername(username);
            }
            System.out.println(user);
        } catch (
                Exception e) {
            e.printStackTrace();
        } finally {
            // 释放资源
            if (resultSet != null) {
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (preparedStatement != null) {
                try {
                    preparedStatement.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
Salin selepas log masuk

Melihat kod tersebut, kami boleh menemui masalah berikut dengan menggunakan JDBC untuk mengendalikan pangkalan data:

  • Penciptaan dan pelepasan sambungan pangkalan data yang kerap menyebabkan pembaziran sumber sistem, sekali gus menjejaskan prestasi sistem.

  • Kami menulis pernyataan SQL dalam kod Kod ini tidak mudah untuk dikekalkan dalam aplikasi sebenar.

  • Menggunakan preparedStatement untuk menghantar parameter kepada simbol yang diduduki adalah dikod keras, kerana keadaan di mana pernyataan sql tidak pasti, mungkin lebih atau kurang untuk mengubah suai sql, anda perlu mengubah suai kod, dan sistem ini tidak mudah diselenggara.

  • Terdapat pengekodan keras (nama lajur pertanyaan) dalam penghuraian set hasil perubahan membawa kepada perubahan dalam kod penghuraian, dan sistem tidak mudah diselenggara boleh dikapsulkan ke dalam objek pojo, ia akan menjadi lebih mudah untuk menghuraikan

Idea penyelesaian masalah

  • Gunakan kumpulan sambungan pangkalan data untuk memulakan sambungan. sumber untuk mengelakkan pembaziran sumber

  • Ekstrak pernyataan sql ke dalam konfigurasi xml ini hanya perlu memfokuskan pada fail xml. Ia tidak lebih baik daripada menulis semula sql dalam a sekumpulan kod java Teknologi seperti introspeksi secara automatik memetakan entiti ke medan jadual.

  • Tulis sendiri rangka kerja lapisan kegigihan

  • Seterusnya, mari selesaikan masalah di atas satu persatu

Kita boleh menggunakan c3p0 terus untuk kumpulan sambungan pangkalan data ComboPooledDataSource yang disediakan boleh digunakan

Untuk menyelesaikan masalah pengekodan keras sql, kita perlu menulis sql ke dalam fail xml, jadi secara semula jadi kita perlu mentakrifkan fail xml.

Sql sahaja sudah pasti tidak mencukupi Lagipun, kita perlu menyambung ke pangkalan data terlebih dahulu sebelum pernyataan sql mempunyai apa-apa makna. Oleh itu, maklumat konfigurasi data mesti ditakrifkan dahulu dalam xml, dan kemudian pernyataan sql.

1. Tentukan fail xml konfigurasi

Kami mencipta sqlMapConfig.xml baharu, mentakrifkan maklumat sumber data dan menambah dua pernyataan sql, parameterType ialah parameter pelaksanaan sql dan resultType ialah entiti pulangan kaedah.

Kod adalah seperti berikut (versi pangkalan data yang berbeza mungkin menggunakan kelas pemacu yang berbeza):

Sekarang maklumat pangkalan data fail xml juga tersedia, dan definisi pernyataan sql ialah ada juga, apa lagi masalah yang ada?

Operasi sql sebenar kami akan melibatkan jadual yang berbeza, jadi kami memperbaikinya dan meletakkan penyata sql setiap jadual dalam xml yang berasingan, supaya strukturnya lebih jelas dan lebih mudah diselenggara.
<configuration>
    <!--数据库连接信息-->
    <property name="driverClass" value="com.mysql.cj.jdbc.Driver"/>
<!--    <property name="driverClass" value="com.mysql.jdbc.Driver"/>-->
    <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=Asia/Shanghai"/>
    <property name="username" value="root"/>
    <property name="password" value="mimashi3124"/>

	<select id="selectOne" parameterType="org.example.pojo.User"
            resultType="org.example.pojo.User">
        select * from user where id = #{id} and username =#{username}
    </select>

    <select id="selectList" resultType="org.example.pojo.User">
        select * from user
    </select>
</configuration>
Salin selepas log masuk

Konfigurasi xml yang dioptimumkan kini seperti ini

sqlMapConfig.xml

mapper.xml

<configuration>
    <!--数据库连接信息-->
    <property name="driverClass" value="com.mysql.cj.jdbc.Driver"/>
	<!-- <property name="driverClass" value="com.mysql.jdbc.Driver"/>-->
    <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=Asia/Shanghai"/>
    <property name="username" value="root"/>
    <property name="password" value="mimashi3124"/>
    <!--引⼊sql配置信息-->
	<mapper resource="mapper.xml"></mapper>
</configuration>
Salin selepas log masuk
Sebenarnya, tentukan Pengguna entiti perniagaan

<mapper namespace="user">
    <select id="selectOne" parameterType="org.example.pojo.User"
            resultType="org.example.pojo.User">
        select * from user where id = #{id} and username =#{username}
    </select>

    <select id="selectList" resultType="org.example.pojo.User">
        select * from user
    </select>
</mapper>
Salin selepas log masuk
2 Baca fail konfigurasi

Selepas bacaan selesai, ia akan wujud dalam bentuk aliran, yang tidak mudah dikendalikan, jadi kita perlu untuk menghuraikan untuk mendapatkan maklumat dan mencipta objek entiti untuk menyimpannya.
public class User {
    private int id;
    private String username;
    
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username=&#39;" + username + &#39;\&#39;&#39; +
                &#39;}&#39;;
    }
}
Salin selepas log masuk

Konfigurasi: menyimpan maklumat pangkalan data asas, Map< pengecam unik Mapper>: ruang nama + "." kami menggunakan dom4j

Mula-mula memperkenalkan kebergantungan maven

Kod adalah seperti berikut (versi pemacu mysql dilaraskan mengikut versi mysql sebenar yang digunakan):

Konfigurasi entiti konfigurasi pangkalan data

Entiti maklumat penyata SQL

<properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.22</version>
        </dependency>
        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.1.2</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
        </dependency>
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6.1</version>
        </dependency>
        <dependency>
            <groupId>jaxen</groupId>
            <artifactId>jaxen</artifactId>
            <version>1.1.6</version>
        </dependency>
    </dependencies>
Salin selepas log masuk

Dengan cara ini, tentukan kelas Sumber untuk membaca aliran fail xml

public class Configuration {
    //数据源
    private DataSource dataSource;
    //map集合: key:statementId value:MappedStatement
    private Map<String,MappedStatement> mappedStatementMap = new HashMap<>();

    public DataSource getDataSource() {
        return dataSource;
    }

    public Configuration setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
        return this;
    }

    public Map<String, MappedStatement> getMappedStatementMap() {
        return mappedStatementMap;
    }

    public Configuration setMappedStatementMap(Map<String, MappedStatement> mappedStatementMap) {
        this.mappedStatementMap = mappedStatementMap;
        return this;
    }
}
Salin selepas log masuk

langkah seterusnya ialah penghuraian sebenar, kerana Terdapat banyak kod penghuraian, jadi kami mempertimbangkan untuk merangkum kelas untuk mengendalikan penghuraian secara berasingan

public class MappedStatement {

    //id
    private String id;
    //sql语句
    private String sql;
    //输⼊参数
    private String parameterType;
    //输出参数
    private String resultType;

    public String getId() {
        return id;
    }

    public MappedStatement setId(String id) {
        this.id = id;
        return this;
    }

    public String getSql() {
        return sql;
    }

    public MappedStatement setSql(String sql) {
        this.sql = sql;
        return this;
    }

    public String getParameterType() {
        return parameterType;
    }

    public MappedStatement setParameterType(String parameterType) {
        this.parameterType = parameterType;
        return this;
    }

    public String getResultType() {
        return resultType;
    }

    public MappedStatement setResultType(String resultType) {
        this.resultType = resultType;
        return this;
    }
}
Salin selepas log masuk
Tentukan kelas XMLConfigBuilder untuk menghuraikan maklumat konfigurasi pangkalan data

public class Resources {
    public static InputStream getResourceAsSteam(String path) {
        return Resources.class.getClassLoader().getResourceAsStream(path);
    }
}
Salin selepas log masuk
Tentukan kelas XMLMapperBuilder untuk menghuraikan maklumat konfigurasi pangkalan data

Kini kita boleh mendapatkan objek Konfigurasi dengan memanggil kaedah penghuraian konfigurasi. Tetapi dalam penggunaan sebenar, kami pasti berharap saya dapat memberi anda maklumat konfigurasi dan pernyataan SQL, dan kemudian memanggil kaedah anda untuk mengembalikan hasilnya.

Jadi kita juga perlu mentakrifkan antara muka operasi pangkalan data (kelas)
public class XMLConfigBuilder {

    private Configuration configuration;


    public XMLConfigBuilder() {
        this.configuration = new Configuration();
    }

    public Configuration parserConfiguration(InputStream inputStream) throws DocumentException, PropertyVetoException, ClassNotFoundException {
        Document document = new SAXReader().read(inputStream);
        Element rootElement = document.getRootElement();
        List<Element> propertyElements = rootElement.selectNodes("//property");
        Properties properties = new Properties();
        for (Element propertyElement : propertyElements) {
            String name = propertyElement.attributeValue("name");
            String value = propertyElement.attributeValue("value");
            properties.setProperty(name,value);
        }
        //解析到数据库配置信息,设置数据源信息
        ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
        comboPooledDataSource.setDriverClass(properties.getProperty("driverClass"));
        comboPooledDataSource.setJdbcUrl(properties.getProperty("jdbcUrl"));
        comboPooledDataSource.setUser(properties.getProperty("username"));
        comboPooledDataSource.setPassword(properties.getProperty("password"));
		
        configuration.setDataSource(comboPooledDataSource);

		//将configuration传入XMLMapperBuilder中做sql语句解析。
        XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(this.configuration);
        List<Element> mapperElements = rootElement.selectNodes("//mapper");
        for (Element mapperElement : mapperElements) {
            String mapperPath = mapperElement.attributeValue("resource");
            InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(mapperPath);
            xmlMapperBuilder.parse(resourceAsStream);
        }
        return configuration;
    }
}
Salin selepas log masuk

3 Tentukan antara muka operasi sql SqlSession

public class XMLMapperBuilder {

    private Configuration configuration;

    public XMLMapperBuilder(Configuration configuration) {
        this.configuration = configuration;
    }
    public void parse(InputStream inputStream) throws DocumentException,
            ClassNotFoundException {
        Document document = new SAXReader().read(inputStream);
        Element rootElement = document.getRootElement();
        String namespace = rootElement.attributeValue("namespace");
        List<Element> select = rootElement.selectNodes("select");
        for (Element element : select) { //id的值
            String id = element.attributeValue("id");
            String parameterType = element.attributeValue("parameterType"); //输⼊参数
            String resultType = element.attributeValue("resultType"); //返回参数
            //statementId,后续调用通过statementId,找到对应的sql执行
            String key = namespace + "." + id;
            //sql语句
            String textTrim = element.getTextTrim();
            //封装 mappedStatement
            MappedStatement mappedStatement = new MappedStatement();
            mappedStatement.setId(id);
            mappedStatement.setParameterType(parameterType);
            mappedStatement.setResultType(resultType);
            mappedStatement.setSql(textTrim);
            //填充 configuration
            configuration.getMappedStatementMap().put(key, mappedStatement);
        }
    }
}
Salin selepas log masuk

Pelaksanaan konkrit antara muka operasi SqlSession, di sini terutamanya melalui. statementId Cari maklumat sql yang sepadan dan laksanakannya

SimpleExcutor dalam kod melakukan pelaksanaan kenyataan pangkalan data sebenar, pengkapsulan parameter kembali dan operasi lain

public interface SqlSession {
	//查询多个
    public <E> List<E> selectList(String statementId, Object... param) throws Exception;

	//查询一个
    public <T> T selectOne(String statementId,Object... params) throws Exception;
}
Salin selepas log masuk
4

Kaedah selectList dalam kelas operasi pangkalan data DefaultSqlSession memanggil kaedah simpleExcutor.query()

Prosesnya adalah
public class DefaultSqlSession implements SqlSession {

    private Configuration configuration;
    private Executor simpleExcutor = new SimpleExecutor();

    public DefaultSqlSession(Configuration configuration) {
        this.configuration = configuration;
    }

    @Override
    public <E> List<E> selectList(String statementId, Object... param) throws Exception {
        MappedStatement mappedStatement =
                configuration.getMappedStatementMap().get(statementId);
        List<E> query = simpleExcutor.query(configuration, mappedStatement, param);
        return query;
    }

    @Override
    public <T> T selectOne(String statementId, Object... params) throws Exception {
        List<Object> objects = selectList(statementId, params);
        if (objects.size() == 1) {
            return (T) objects.get(0);
        } else {
            throw new RuntimeException("返回结果过多");
        }
    }
}
Salin selepas log masuk

diperolehi mengikut statementId yang sepadan dengan pernyataan sql yang akan dilaksanakan, parameter panggilan dan parameter pulangan.

public class SimpleExecutor implements Executor {

    private Connection connection = null;

    @Override
    public <E> List<E> query(Configuration configuration, MappedStatement mappedStatement, Object[] params) throws Exception {
        //获取连接
        connection = configuration.getDataSource().getConnection();
        // select * from user where id = #{id} and username = #{username} String sql =
        String sql = mappedStatement.getSql();
        //对sql进⾏处理
        BoundSql boundSql = getBoundSql(sql);
        // 3.获取预处理对象:preparedStatement
        PreparedStatement preparedStatement = connection.prepareStatement(boundSql.getSqlText());

        // 4. 设置参数
        //获取到了参数的全路径
        String parameterType = mappedStatement.getParameterType();
        Class<?> parameterTypeClass = getClassType(parameterType);

        List<ParameterMapping> parameterMappingList = boundSql.getParameterMappingList();
        for (int i = 0; i < parameterMappingList.size(); i++) {
            ParameterMapping parameterMapping = parameterMappingList.get(i);
            String content = parameterMapping.getContent();

            //反射
            Field declaredField = parameterTypeClass.getDeclaredField(content);
            //暴力访问
            declaredField.setAccessible(true);
            Object o = declaredField.get(params[0]);

            preparedStatement.setObject(i+1,o);

        }
        // 5. 执行sql
        ResultSet resultSet = preparedStatement.executeQuery();
        String resultType = mappedStatement.getResultType();
        Class<?> resultTypeClass = getClassType(resultType);

        ArrayList<Object> objects = new ArrayList<>();

        // 6. 封装返回结果集
        while (resultSet.next()){
            Object o =resultTypeClass.newInstance();
            //元数据
            ResultSetMetaData metaData = resultSet.getMetaData();
            for (int i = 1; i <= metaData.getColumnCount(); i++) {
                // 字段名
                String columnName = metaData.getColumnName(i);
                // 字段的值
                Object value = resultSet.getObject(columnName);
                //使用反射或者内省,根据数据库表和实体的对应关系,完成封装
                PropertyDescriptor propertyDescriptor = new PropertyDescriptor(columnName, resultTypeClass);
                Method writeMethod = propertyDescriptor.getWriteMethod();
                writeMethod.invoke(o,value);
            }
            objects.add(o);
        }
        return (List<E>) objects;
    }

    @Override
    public void close() throws SQLException {

    }

    private Class<?> getClassType(String parameterType) throws ClassNotFoundException {
        if(parameterType!=null){
            Class<?> aClass = Class.forName(parameterType);
            return aClass;
        }
        return null;

    }

    private BoundSql getBoundSql(String sql) {
        //标记处理类:主要是配合通⽤标记解析器GenericTokenParser类完成对配置⽂件等的解 析⼯作,其中
        //TokenHandler主要完成处理
        ParameterMappingTokenHandler parameterMappingTokenHandler = new
                ParameterMappingTokenHandler();
        //GenericTokenParser :通⽤的标记解析器,完成了代码⽚段中的占位符的解析,然后再根 据给定的
       // 标记处理器(TokenHandler)来进⾏表达式的处理
        //三个参数:分别为openToken (开始标记)、closeToken (结束标记)、handler (标记处 理器)
        GenericTokenParser genericTokenParser = new GenericTokenParser("#{", "}",
                parameterMappingTokenHandler);
        String parse = genericTokenParser.parse(sql);
        List<ParameterMapping> parameterMappings =
                parameterMappingTokenHandler.getParameterMappings();
        return new BoundSql(parse, parameterMappings);
    }
}
Salin selepas log masuk

Menghuraikan pemegang tempat sql dan tetapkan parameter panggilan
  • Mengikut medan parameter input yang dihuraikan, dapatkan nilai yang sepadan melalui nilai pantulan, tetapkan parameter pernyataan sql
  • laksanakan pernyataan sql, gunakan refleksi dan introspeksi, lengkapkan tetapan atribut objek mengikut hubungan yang sepadan antara jadual pangkalan data dan entiti, dan akhirnya kembalikan hasil.
  • Melalui langkah di atas, kami memperoleh konfigurasi pangkalan data dan maklumat pernyataan sql. Kelas operasi pangkalan data SqlSession ditakrifkan, tetapi kami tidak memanggil fail konfigurasi parsing di mana-mana sahaja.
  • 我们还需要一个东西把两者给串起来,这里我们可以使用工厂模式来生成SqlSession

    使用工厂模式创建SqlSession

    public interface SqlSessionFactory {
        public SqlSession openSession();
    }
    Salin selepas log masuk
    public class DefaultSqlSessionFactory implements SqlSessionFactory{
    
        private Configuration configuration;
    
        public DefaultSqlSessionFactory(Configuration configuration) {
            this.configuration = configuration;
        }
    
        @Override
        public SqlSession openSession() {
            return new DefaultSqlSession(configuration);
        }
    }
    Salin selepas log masuk

    同时为了屏蔽构建SqlSessionFactory工厂类时获取Configuration的解析过程,我们可以使用构建者模式来获得一个SqlSessionFactory类。

    public class SqlSessionFactoryBuilder {
        public SqlSessionFactory build(InputStream inputStream) throws PropertyVetoException, DocumentException, ClassNotFoundException {
            XMLConfigBuilder xmlConfigerBuilder = new XMLConfigBuilder();
            Configuration configuration = xmlConfigerBuilder.parserConfiguration(inputStream);
            SqlSessionFactory sqlSessionFactory = new DefaultSqlSessionFactory(configuration);
            return sqlSessionFactory;
        }
    }
    Salin selepas log masuk

    5.调用测试

    终于好了,通过以上几个步骤我们现在可以具体调用执行代码了。

     public static void main(String[] args) throws Exception {
            InputStream resourceAsSteam = Resources.getResourceAsSteam("sqlMapConfig.xml");
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsSteam);
            SqlSession sqlSession = sqlSessionFactory.openSession();
            User user = new User();
            user.setId(1);
            user.setUsername("盖伦");
            User user2 = sqlSession.selectOne("user.selectOne", user);
    
            System.out.println(user2);
            List<User> users = sqlSession.selectList("user.selectList");
            for (User user1 : users) {
                System.out.println(user1);
            }
        }
    Salin selepas log masuk

    代码正确执行,输出

    Bagaimana untuk menulis rangka kerja lapisan kegigihan dalam Java

    ⾃定义框架优化

    上述⾃定义框架,解决了JDBC操作数据库带来的⼀些问题:例如频繁创建释放数据库连接,硬编
    码,⼿动封装返回结果集等问题,现在我们继续来分析刚刚完成的⾃定义框架代码,有没有什么问题呢?

    问题如下:

    • dao的实现类中存在重复的代码,整个操作的过程模板重复(创建sqlsession,调⽤sqlsession⽅ 法,关闭sqlsession)

    • dao的实现类中存在硬编码,调⽤sqlsession的⽅法时,参数statement的id硬编码

    我们可以使用代理模式,生成代理对象,在调用之前获取到执行方法的方法名、具体类。这样我们就能获取到statementId。

    为SqlSession类新增getMappper方法,获取代理对象

    public interface SqlSession {
        public <E> List<E> selectList(String statementId, Object... param) throws Exception;
    
        public <T> T selectOne(String statementId,Object... params) throws Exception;
    
        //为Dao接口生成代理实现类
        public <T> T getMapper(Class<?> mapperClass);
    }
    Salin selepas log masuk
    public class DefaultSqlSession implements SqlSession {
    
        private Configuration configuration;
        private Executor simpleExcutor = new SimpleExecutor();
    
        public DefaultSqlSession(Configuration configuration) {
            this.configuration = configuration;
        }
    
        @Override
        public <E> List<E> selectList(String statementId, Object... param) throws Exception {
            MappedStatement mappedStatement =
                    configuration.getMappedStatementMap().get(statementId);
            List<E> query = simpleExcutor.query(configuration, mappedStatement, param);
            return query;
        }
    
        @Override
        public <T> T selectOne(String statementId, Object... params) throws Exception {
            List<Object> objects = selectList(statementId, params);
            if (objects.size() == 1) {
                return (T) objects.get(0);
            } else {
                throw new RuntimeException("返回结果过多");
            }
        }
    
        @Override
        public <T> T getMapper(Class<?> mapperClass) {
            Object proxyInstance = Proxy.newProxyInstance(DefaultSqlSession.class.getClassLoader(), new Class[]{mapperClass}, new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                	// selectOne
                    String methodName = method.getName();
                    // className:namespace
                    String className = method.getDeclaringClass().getName();
                    //statementId
                    String statementId = className+&#39;.&#39;+methodName;
                    Type genericReturnType = method.getGenericReturnType();
                    //判断是否实现泛型类型参数化
                    if (genericReturnType instanceof ParameterizedType){
                        List<Object> objects = selectList(statementId,args);
                        return objects;
                    }
                    return selectOne(statementId,args);
                }
            });
            return (T) proxyInstance;
        }
    }
    Salin selepas log masuk

    定义业务数据dao接口

    public interface IUserDao {
        //查询所有用户
        public List<User> findAll() throws Exception;
        //根据条件进行用户查询
        public User findByCondition(User user) throws Exception;
    }
    Salin selepas log masuk

    接下来我们只需获取到代理对象,调用方法即可。

    public class Main2 {
        public static void main(String[] args) throws Exception {
            InputStream resourceAsSteam = Resources.getResourceAsSteam("sqlMapConfig.xml");
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsSteam);
            SqlSession sqlSession = sqlSessionFactory.openSession();
    		//获取到代理对象
            IUserDao userDao = sqlSession.getMapper(IUserDao.class);
            List<User> all = userDao.findAll();
            for (User user1 : all) {
                System.out.println(user1);
            }
        }
    }
    Salin selepas log masuk

    Bagaimana untuk menulis rangka kerja lapisan kegigihan dalam Java

    Atas ialah kandungan terperinci Bagaimana untuk menulis rangka kerja lapisan kegigihan dalam Java. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:yisu.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan