Up ;)

Nobody thinks it can be useful?

/me still waits for some feedbacks before commiting a first version...

- Romain

Le 29 juil. 2011 22:37, "Romain Manni-Bucau" <[email protected]> a
écrit :
> Here is a patch:
>
> http://pastebin.com/4CgcLkmH
>
> it is a bit dirty at JNDI level but it works if you want to try:
>
> The repository:
>
> @Repository(context = @PersistenceContext(unitName = "user"))
> public interface UserDAO {
> User findById(long id);
> Collection<User> findByName(String name);
> Collection<User> findAll();
> }
>
> An entity:
>
> @Entity
> public class User {
> @Id @GeneratedValue private long id;
> private String name;
> private int age;
>
> public long getId() {
> return id;
> }
>
> public void setId(long 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;
> }
>
> @Override
> public String toString() {
> return "User{" +
> "id=" + id +
> ", name='" + name + '\'' +
> ", age=" + age +
> '}';
> }
> }
>
> A stateless to init the database:
>
> @Stateless
> public class InitUserDAO {
> @PersistenceContext private EntityManager em;
> public void insert(User user) {
> em.persist(user);
> }
> }
>
> The test:
>
> package org.superbiz.test;
>
> import org.junit.AfterClass;
> import org.junit.BeforeClass;
> import org.junit.Ignore;
> import org.junit.Test;
> import org.superbiz.dao.InitUserDAO;
> import org.superbiz.dao.UserDAO;
> import org.superbiz.model.User;
>
> import javax.ejb.embeddable.EJBContainer;
> import javax.naming.Context;
> import java.util.Collection;
>
> /**
> * @author rmannibucau
> */
> public class QueryTest {
> private static Context context;
> private static UserDAO dao;
>
> @BeforeClass public static void init() throws Exception {
> context = EJBContainer.createEJBContainer().getContext();
> InitUserDAO init = (InitUserDAO)
> context.lookup("java:global/dynamic-query/InitUserDAO");
> dao = (UserDAO) context.lookup("java:global/openejb/Repository/" +
> UserDAO.class.getName());
> for (int i = 0; i < 10; i++) {
> User u = new User();
> u.setAge(i * 8);
> if (i % 3 == 0) {
> u.setName("foo");
> } else {
> u.setName("bar-" + i);
> }
> init.insert(u);
> }
> }
>
> @AfterClass public static void close() throws Exception {
> if (context != null) {
> context.close();
> }
> }
>
> @Test public void query() {
> Collection<User> u1 = dao.findByName("foo");
> Collection<User> users = dao.findAll();
> User u2 = dao.findById(1);
> System.out.println("\n\n" + users + "\n\n" + u1 + "\n\n" + u2);
> }
> }
>
> and the persistence.xml:
>
> <persistence xmlns="http://java.sun.com/xml/ns/persistence";
> version="2.0"
> 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";>
> <persistence-unit name="user" transaction-type="JTA">
> <jta-data-source>My Default DataSource</jta-data-source>
> <class>org.superbiz.model.User</class>
> <properties>
> <property name="openjpa.jdbc.SynchronizeMappings"
> value="buildSchema(ForeignKeys=true)"/>
> </properties>
> </persistence-unit>
> </persistence>
>
> Don't hesitate to give me feedback if i should continue or not, what you
> think should be done or not.
>
> - Romain
>
> 2011/7/29 Romain Manni-Bucau <[email protected]>
>
>> Hi,
>>
>> i discover a bit more spring data jpa and saw it was possible to create
>> dynamically classes!!
>>
>> it is exactly the same than the stateless without interface excepted here
>> the interface has no implementation.
>>
>> what do you think if we had it to OpenEJB, it is not standard but it is
>> pretty cool.
>>
>> Here what i think we could do:
>>
>> 1. create a API to scan interfaces
>> 1. we need persistencecontext information so we could use
>> @PersistenceContext (i don't like) or add another annotation withthe same
>> information (@Repository?)
>> 2. we need a name, @Named can probably used or we can add it to
>> @Repository
>> 2. we scan "@Repository" interface constructing pseudo injection to
>> be able to get an entitymanager
>> 3. then we deploy it in JNDI
>> 1. instead of binding a class we bind a proxy which manage to create
>> the query from the name
>>
>>
>> It is probably no clear so here some snippets:
>>
>> My repository:
>>
>> @Repository(name = "user")
>> public interface UserDAO {
>> User findById(long id);
>> Collection<User> findByName(String name);
>> Collection<User> findAll();
>> }
>>
>>
>> One very simple implementation of the invocation handler which manage
only
>> one condition (this version need an EntityManagerHolder which is here
only
>> to be able to get the em, it is just an interface with a method
>> getEntityManager()...just to do the poc):
>>
>>
>> public class QueryProxy<T> implements InvocationHandler {
>> public static final String FIND_PREFIX = "find";
>>
>> private static final Map<String, List<String>> CONDITIONS = new
>> ConcurrentHashMap<String, List<String>>();
>>
>> private EntityManagerHolder entityManagerHolder;
>> private Class<T> type;
>>
>> public QueryProxy(EntityManagerHolder holder, Class<T> entityClass) {
>> entityManagerHolder = holder;
>> type = entityClass;
>> }
>>
>> public Object invoke(Object proxy, Method method, Object[] args) throws
>> Throwable {
>> if (!method.getName().startsWith(FIND_PREFIX)) {
>> throw new IllegalArgumentException("finder should start with
>> find");
>> }
>>
>> Query query = getQuery(entityManagerHolder.getEntityManager(),
>> method.getName(), args);
>> if (Collection.class.isAssignableFrom(method.getReturnType())) {
>> return query.getResultList();
>> }
>> return query.getSingleResult();
>> }
>>
>> private Query getQuery(EntityManager entityManager, String methodName,
>> Object[] args) {
>> final List<String> conditions = parseMethodName(methodName);
>> final EntityType<T> et = entityManager.getMetamodel().entity(type);
>> final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
>>
>> CriteriaQuery<Object> query = cb.createQuery();
>> Root<T> from = query.from(type);
>> query = query.select(from);
>>
>> int i = 0;
>> for (String condition : conditions) {
>> SingularAttribute<? super T, ?> attribute =
>> et.getSingularAttribute(condition);
>> Path<?> path = from.get(attribute);
>> Class<?> javaType = attribute.getType().getJavaType();
>> if (javaType.equals(String.class)) {
>> query = query.where(cb.like((Expression<String>) path,
>> (String) args[i++]));
>> } else if (Number.class.isAssignableFrom(javaType) ||
>> javaType.isPrimitive()) {
>> query = query.where(cb.equal(path, args[i++]));
>> }
>> }
>>
>> return entityManager.createQuery(query);
>> }
>>
>> private List<String> parseMethodName(final String methodName) {
>> List<String> parsed;
>> if (CONDITIONS.containsKey(methodName)) {
>> parsed = CONDITIONS.get(methodName);
>> } else {
>> parsed = new ArrayList<String>();
>> String toParse = methodName.substring(FIND_PREFIX.length());
>> // TODO
>> if (toParse.startsWith("By")) {
>> toParse = StringUtils.uncapitalize(toParse.substring(2));
>> parsed.add(toParse);
>> }
>> CONDITIONS.put(methodName, parsed);
>> }
>> return parsed;
>> }
>> }
>>
>>
>> Finally i can do:
>>
>> public class QueryTest {
>> private static Context context;
>> private static UserDAO dao;
>>
>> @BeforeClass public static void init() throws Exception {
>> context = EJBContainer.createEJBContainer().getContext();
>> dao = (UserDAO)
>> Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
>> new Class<?>[] { UserDAO.class },
>> new QueryProxy((EntityManagerHolder)
>> context.lookup("java:global/dynamic-query/EMH"), User.class));
>>
>>
>> InitUserDAO init = (InitUserDAO)
>> context.lookup("java:global/dynamic-query/InitUserDAO");
>> for (int i = 0; i < 10; i++) {
>> User u = new User();
>> u.setAge(i * 8);
>> if (i % 3 == 0) {
>> u.setName("foo");
>> } else {
>> u.setName("bar-" + i);
>> }
>> init.insert(u);
>> }
>> }
>>
>> @AfterClass public static void close() throws Exception {
>> if (context != null) {
>> context.close();
>> }
>> }
>>
>> @Test public void query() {
>> Collection<User> u1 = dao.findByName("foo");
>> Collection<User> users = dao.findAll();
>> User u2 = dao.findById(1);
>> System.out.println("\n\n" + users + "\n\n" + u1 + "\n\n" + u2);
>> }
>> }
>>
>> Any thoughts? should it be added to OpenEJB (after some enhancement of
>> course ;))?
>>
>>
>> we could extend it to persist, update etc... methods
>>
>>
>> - Romain
>>
>>
>>
>>
>>

Reply via email to